Skip to content

Latest commit

 

History

History
115 lines (81 loc) · 2.78 KB

File metadata and controls

115 lines (81 loc) · 2.78 KB

Contents

  1. Designated initializer
  2. constinit
  3. Range-based for loop initializer

⬅️ Back to Contents

Designated initializer

struct User {
  std::string email;
  std::string password;
  int pin;
};

int main() {
  User jason{"jason@mail.com", "Passw0rd!", 1234}; // good old struct initialization
  User jane{.email = "jane@mail.com", .password = "Passw0rd!"}; // designated initialization
}
  • Only for aggregate types

    An aggregate is an array or a class with

    • no user-declared or inherited constructors

    • no private or protected non-static data members

    • no virtual functions

    • no virtual, private, or protected base classes

    struct Widget {
      Widget() = delete;
    };
    
    Widget w; // error
    Widget w{}; // ok in C++17 whereas in C++20 it is error
  • All designators used in the expression must appear in the same order as the data members, e.g.

User user{.password = "Passw0rd!", .email = "user@mail.com"};

error: ISO C++ requires field designators to be specified in declaration order ...

  • Also, cannot be mixed with regular initializers
User user{.email = "user@mail.com", "Passw0rd!"};

error: mixture of designated and non-designated initializers in the same initializer list ...

⬆️ Back to Contents

constinit

constinit specifies that a variable must have a static initialization.

constinit cannot be used together with constexpr or consteval.

const char* AllocateDynamicString() {
  return "Dynamic init";
}

constexpr const char* GetString(bool isConstInit) {
  return isConstInit ? "Const init" : AllocateDynamicString();
}

constinit const char* str = GetString(true); // ok
constinit const char* str = GetString(false); // error: variable does not have a constant initializer

📎 constinit can only be applied to variables with static or thread storage duration. It does not make sense to apply it to other variables, as constinit is all about static initialization.

⬆️ Back to Contents

Range-based for loop initializer

for (const auto& user : GetDatabase().selectActiveUsers()) { // not good enough
  // ...
}

Maybe undefined behaviour because GetDatabase() might returns a reference.

{
  auto db = GetDatabase();
  for (const auto& user : db.selectActiveUsers()) { // good
    // ...
  }
}
for (const auto db = GetDatabase(); const auto& user : db.selectActiveUsers()) { // better
  // ...
}

⬆️ Back to Contents