C++17/20 집합 초기화(Aggregate Initialization)
집합(Aggregate)이란
섹션 제목: “집합(Aggregate)이란”집합 초기화 대상이 되는 타입의 조건은 C++ 버전마다 완화되어 왔습니다.
| 조건 | C++11/14 | C++17 | C++20 |
|---|---|---|---|
| 사용자 선언 생성자 없음 | ✅ | ✅ | ✅ |
private/protected 비정적 멤버 없음 | ✅ | ✅ | ✅ |
| 기반 클래스 없음 | ✅ | ❌ 완화 | ❌ 완화 |
virtual 함수 없음 | ✅ | ✅ | ✅ |
explicit 생성자 없음 | — | — | ✅ (상속된 것도) |
C++17: 기반 클래스도 집합 초기화 가능
섹션 제목: “C++17: 기반 클래스도 집합 초기화 가능”struct Base { int x; double y;};
struct Derived : Base { std::string name;};
// C++17부터 가능Derived d{ {1, 2.0}, "hello" };// 또는 중첩 braces 생략Derived d2{ 1, 2.0, "hello" };C++20: 지정 초기화자(Designated Initializers)
섹션 제목: “C++20: 지정 초기화자(Designated Initializers)”멤버 이름을 명시해 초기화합니다. C의 designated initializer와 유사하지만 순서를 지켜야 합니다.
struct Config { int width = 800; int height = 600; bool fullscreen = false; std::string title = "App";};
Config cfg{ .width = 1920, .height = 1080, .fullscreen = true, // title은 기본값 "App" 사용};지정하지 않은 멤버는 기본 멤버 초기화값 또는 zero-initialization이 적용됩니다.
순서 제약
섹션 제목: “순서 제약”C++20 지정 초기화자는 선언 순서를 따라야 합니다(C와 달리 순서 변경 불가).
struct Point { int x, y, z; };
Point p1{ .x = 1, .y = 2, .z = 3 }; // OKPoint p2{ .z = 3, .x = 1 }; // 오류: 순서 위반중첩 집합 초기화
섹션 제목: “중첩 집합 초기화”struct Window { Config config; int monitor = 0;};
Window w{ .config = { .width = 1280, .height = 720 }, .monitor = 1,};집합 초기화 vs 생성자
섹션 제목: “집합 초기화 vs 생성자”struct WithCtor { int x; WithCtor(int v) : x(v) {} // 사용자 정의 생성자 → 집합 아님};
struct Aggregate { int x; // 생성자 없음 → 집합};
WithCtor a{5}; // 생성자 호출Aggregate b{5}; // 집합 초기화C++20에서는 explicit 생성자를 가진 타입도 집합에서 제외됩니다.
실용 패턴: 설정 구조체
섹션 제목: “실용 패턴: 설정 구조체”struct RenderOptions { int msaa_samples = 4; bool vsync = true; float render_scale = 1.0f; bool hdr_enabled = false;};
void init_renderer(const RenderOptions& opts = {});
// 호출: 변경하고 싶은 것만 지정init_renderer({ .msaa_samples = 8, .hdr_enabled = true });Named parameter idiom을 지정 초기화자로 깔끔하게 구현할 수 있습니다.
- C++17에서 기반 클래스를 가진 구조체도 집합 초기화 가능
- C++20 지정 초기화자로 멤버 이름을 명시해 가독성 향상
- 순서는 선언 순서를 따라야 하고, 생략된 멤버는 기본값 적용
- 설정 구조체 패턴과 결합하면 named parameter 효과를 낼 수 있음