콘텐츠로 이동

C++17/20 집합 초기화(Aggregate Initialization)

집합 초기화 대상이 되는 타입의 조건은 C++ 버전마다 완화되어 왔습니다.

조건C++11/14C++17C++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 }; // OK
Point p2{ .z = 3, .x = 1 }; // 오류: 순서 위반
struct Window {
Config config;
int monitor = 0;
};
Window w{
.config = { .width = 1280, .height = 720 },
.monitor = 1,
};
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 효과를 낼 수 있음