yohhoyの日記

技術的メモをしていきたい日記

Designated Initialization @ C++

C++2a(C++20)で導入予定のDesignated Initialization(指示付きの初期化)ついてメモ。C99での同一言語機能をベースとするが、一部機能制限された形でC++に導入される。

// C++2a(C++20)
struct Point { int x, y; };
void f(Point);

f({ .x = 100, .y = 50 });  // OK: Designated Initialization

// 指示子順==メンバ宣言順 が条件
f({ .y = 50, .x = 100 });  // NG

C++2a言語機能とC99言語機能との差異は下表の通り(P0329R0より引用)。特に初期化子順序をデータメンバ宣言順と一致させる必要がある点に注意。関数呼び出しの名前付きパラメータ(named parameter)的な利用方法には使いづらそう。

C++2a C99 コード例
指示子順とメンバ宣言順の一致が必要 指示子順序は任意 C99ではOK/C++2aではNG
struct { int a, b; };
A a = { .b = 3, .a = 4 };
指示付き初期化の評価順序は左から右 初期化の評価順序は未規定*1 *2
全て指示付き、または全て指示無し 混在可能 C99ではOK/C++2aではNG
A a = { 3, .a = 4 };
指示付き初期化は重複不可 重複可能 C99ではOK/C++2aではNG
A a = { .a = 3, .a = 4 };
配列型には非対応 配列要素の初期化に対応 C99ではOK/C++2aではNG
A a = { [3] = 4 };
指示付き初期化のネスト不可 ネスト対応 C99ではOK/C++2aではNG
A a = { .e.a = 3 };
統一初期化に対応 (Cの初期化子のみ) C++2aのみOK
A a = { .a{} };

Working Draft N4687 C.1.7, 11.6.1より引用。

Change: In C++, designated initialization support is restricted compared to the corresponding functionality in C. In C++, designators for non-static data members must be specified in declaration order, designators for array elements and nested designators are not supported, and designated and non-designated initializers cannot be mixed in the same initializer list.
Example:

struct A { int x, y; };
struct B { struct A a; };
struct A a = {.y = 1, .x = 2};  // valid C, invalid C++
int arr[3] = {[1] = 5};         // valid C, invalid C++
struct B b = {.a.x = 0};        // valid C, invalid C++
struct A c = {.x = 1, 2};       // valid C, invalid C++

Rationale: In C++, members are destroyed in reverse construction order and the elements of an initializer list are evaluated in lexical order, so field initializers must be specified in order. Array designators conflict with lambda-expression syntax. Nested designators are seldom used.
Effect on original feature: Deletion of feature that is incompatible with C++.
Difficulty of converting: Syntactic transformation.
How widely used: Out-of-order initializers are common. The other features are seldom used.

N4687 Working Draft, Standard for Programming Language C++

関連URL

*1:C99 6.7.8/p23: The order in which any side effects occur among the initialization list expressions is unspecified.

*2:C11 6.7.9/p23: The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.