C++20 Designated Initializers Complete Guide | Clear Struct Initialization

C++20 Designated Initializers Complete Guide | Clear Struct Initialization

이 글의 핵심

C++20 Designated Initializers: clear struct initialization. What are Designated Initializers? Why needed and basic syntax as axes, explaining syntax, patterns, and precautions with examples.

What are Designated Initializers? Why Needed?

Problem Scenario: Confusion in Struct Initialization

Problem: When struct has many members, listing values in order makes it unclear which value belongs to which member. Below is an implementation example using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Config {
    std::string host;
    int port;
    bool ssl;
    int timeout;
    int max_connections;
};
int main() {
    // Unclear which value is which member
    Config cfg = {"localhost", 8080, true, 30, 100};
    // Is port 8080? Is timeout 30?
}

Solution: Designated Initializers (C++20) initialize by specifying member names. Code becomes clear and safe even when member order changes. Below is an implementation example using C++. Understand the role of each part while examining the code.

int main() {
    Config cfg = {
        .host = "localhost",
        .port = 8080,
        .ssl = true,
        .timeout = 30,
        .max_connections = 100
    };
    // Clear and readable!
}

1. Basic Syntax

Basic Usage

Below is an implementation example using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Point {
    int x;
    int y;
};
int main() {
    // C++20 Designated Initializers
    Point p1 = {.x = 10, .y = 20};
    
    // Can omit braces
    Point p2{.x = 30, .y = 40};
    
    std::cout << p1.x << ", " << p1.y << '\n';  // 10, 20
}

Comparison with Regular Initialization

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Person {
    std::string name;
    int age;
    std::string city;
};
int main() {
    // Regular initialization (order matters)
    Person p1 = {"Alice", 30, "Seoul"};
    
    // Designated Initializers (specify member names)
    Person p2 = {
        .name = "Bob",
        .age = 25,
        .city = "Busan"
    };
}

2. Order Rules

Declaration Order Must Be Maintained

In C++20, Designated Initializers must follow declaration order (different from C). Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Data {
    int a;
    int b;
    int c;
};
int main() {
    // ✅ In declaration order
    Data d1 = {.a = 1, .b = 2, .c = 3};  // OK
    
    // ❌ Order violation
    // Data d2 = {.b = 2, .a = 1, .c = 3};  // Error in C++20
    
    // ✅ Skipping is OK
    Data d3 = {.a = 1, .c = 3};  // b = 0 (default value)
}

C vs C++20 Difference

ItemCC++20
OrderFreeDeclaration order required
MixingAllowedNot allowed
ArrayFree indexSequential only
// OK in C
struct Data { int a, b, c; };
Data d = {.c = 3, .a = 1, .b = 2};  // C: OK, C++20: Error

3. Nested Structs

Nested Initialization

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Address {
    std::string city;
    std::string street;
    int zipcode;
};
struct Employee {
    std::string name;
    int id;
    Address address;
};
int main() {
    Employee emp = {
        .name = "Alice",
        .id = 1001,
        .address = {
            .city = "Seoul",
            .street = "Gangnam",
            .zipcode = 12345
        }
    };
    
    std::cout << emp.name << ", " << emp.address.city << '\n';
}

4. Default Values and Partial Initialization

Partial Initialization

Here is detailed implementation code using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.

struct Config {
    std::string host = "localhost";
    int port = 8080;
    bool ssl = false;
    int timeout = 30;
};
int main() {
    // Only specify some members
    Config cfg1 = {.port = 9000};
    // host="localhost", port=9000, ssl=false, timeout=30
    
    Config cfg2 = {.host = "example.com", .ssl = true};
    // host="example.com", port=8080, ssl=true, timeout=30
}

Zero Initialization

struct Data {
    int a;
    int b;
    int c;
};
int main() {
    // Unspecified members are zero-initialized
    Data d = {.a = 10};  // a=10, b=0, c=0
}

Summary

Key Points

  1. Designated Initializers: C++20 feature for clear initialization
  2. Syntax: .member = value format
  3. Order: Must follow declaration order
  4. Partial: Unspecified members use default/zero
  5. Nested: Can nest for complex structures

When to Use

Use Designated Initializers when:

  • Struct has many members
  • Want clear, self-documenting code
  • Need to skip some members
  • Initializing config/option structs ❌ Don’t use when:
  • C++17 or earlier (not supported)
  • Need out-of-order initialization
  • Working with non-aggregate types

Best Practices

  • ✅ Use for config/option structs
  • ✅ Provide default values for optional members
  • ✅ Follow declaration order
  • ❌ Don’t mix with positional initialization
  • ❌ Don’t use with non-aggregate types