Skip to content

Commit 82b627c

Browse files
committed
C++26: 「std::initializer_listの配列を静的記憶域に配置する」を追加 (close #1171)
1 parent f91ef86 commit 82b627c

4 files changed

Lines changed: 88 additions & 3 deletions

File tree

implementation-status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@
291291

292292
| 言語機能 | 説明 | [GCC][gcc] | [Clang][clang] | [ICX][icx] | [MSVC][msvc] |
293293
|----------|------|------------|----------------|------------|--------------|
294-
| P2752R3: [`std::initializer_list`の配列を静的ストレージに配置する](/lang/cpp26/static_storage_for_braced_initializers.md.nolink) | `std::vector v = {1, 2, 3};`のような初期化で初期化子リストを静的ストレージに配置することで無駄なコピーをなくす | 14 | | | |
294+
| P2752R3: [`std::initializer_list`の配列を静的記憶域に配置する](/lang/cpp26/static_storage_for_braced_initializers.md) | `std::vector v = {1, 2, 3};`のような初期化で初期化子リストを静的記憶域に配置することで無駄なコピーをなくす | 14 | | | |
295295
| P2169R4: [宣言のみで使用しない変数の名前として`_`をサポート](/lang/cpp26/nice_placeholder_with_no_name.md) | 変数名`_`は暗黙で`[[maybe_unused]]`が指定される | 14 | 18 | | |
296296
| P1854R4: [文字列リテラルの文字エンコーディング失敗を不適格とする](/lang/cpp26/making_non-encodable_string_literals_ill-formed.md) | 文字列リテラルのエンコーディング時に文字表現が失われる場合にコンパイルエラーにする | 14 | 14 | | |
297297
| P2361R6: [コンパイル時にのみ使用される文字列の扱いを明確化](/lang/cpp26/unevaluated_strings.md.nolink) | `static_assert``[[deprecated]]`などで使用されるコンパイル時の文字列について、文字コードの指定を禁止し、実行時エンコーディングが行われないことを規定 | 14 | 18 | | |

lang/cpp11/initializer_lists.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ std::vector<int> v(ar, ar + N);
341341

342342
## <a id="relative-page" href="#relative-page">関連項目</a>
343343
- [C++11 一様初期化](uniform_initialization.md)
344+
- [C++26 `std::initializer_list`の配列を静的記憶域に配置する](/lang/cpp26/static_storage_for_braced_initializers.md)
344345

345346

346347
## 参照
@@ -357,4 +358,4 @@ std::vector<int> v(ar, ar + N);
357358
- [N2575 Initializer Lists - Alternative Mechanism and Rationale](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2575.pdf)
358359
- [N2640 Initializer Lists - Alternative Mechanism and Rationale (v. 2)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2640.pdf)
359360
- [N2672 Initializer List proposed wording](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm)
360-
- [CWG Issue 1030. Evaluation order in initializer-lists used in aggregate initialization](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030)
361+
- [CWG Issue 1030. Evaluation order in initializer-lists used in aggregate initialization](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030)

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
1111

1212
| 言語機能 | 説明 |
1313
|----------|------|
14-
| [`std::initializer_list`の配列を静的ストレージに配置する](/lang/cpp26/static_storage_for_braced_initializers.md.nolink) | `std::vector v = {1, 2, 3};`のような初期化で初期化子リストを静的ストレージに配置することで無駄なコピーをなくす |
14+
| [`std::initializer_list`の配列を静的記憶域に配置する](/lang/cpp26/static_storage_for_braced_initializers.md) | `std::vector v = {1, 2, 3};`のような初期化で初期化子リストを静的記憶域に配置することで無駄なコピーをなくす |
1515
| [宣言のみで使用しない変数の名前として`_`をサポート](/lang/cpp26/nice_placeholder_with_no_name.md) | 変数名`_`は暗黙で`[[maybe_unused]]`が指定される |
1616
| [非推奨となっていた列挙型の算術変換を削除](/lang/cpp26/remove_deprecated_arithmetic_conversion_on_enumerations.md) | C++20から非推奨となっていた列挙値への算術演算で算術型に暗黙変換される仕様を削除 |
1717
| [不完全型へのポインタに対する`delete`を不適格とする](/lang/cpp26/deleting_a_pointer_to_an_incomplete_type_should_be_ill-formed.md.nolink) | 未定義動作を引き起こす操作をコンパイルエラーとする |
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# std::initializer_listの配列を静的記憶域に配置する [P2752R3]
2+
* cpp26[meta cpp]
3+
4+
<!-- start lang caution -->
5+
6+
このページはC++26に採用される見込みの言語機能の変更を解説しています。
7+
8+
のちのC++規格でさらに変更される場合があるため[関連項目](#relative-page)を参照してください。
9+
10+
<!-- last lang caution -->
11+
12+
## 概要
13+
C++11で導入された[`std::initializer_list`](/reference/initializer_list/initializer_list.md)は、自作クラスで組み込み配列のような配列初期化をする構文であるが、そのメモリとしてはスタック上に配置されていた。
14+
15+
```cpp
16+
std::vector<int> v = {1, 2, 3};
17+
18+
// 以下と等価:
19+
const int __a[] = {1, 2, 3};
20+
std::vector<int> v(__a, __a + 3);
21+
```
22+
23+
C++26では、プリプロセス時にファイル読み込む[`#embed`](/lang/cpp26/embed.md)機能が導入されることもあり、スタックオーバーフローのリスクがあった。
24+
25+
```cpp
26+
std::vector<char> v = {
27+
#embed "2mb-image.png"
28+
};
29+
```
30+
31+
このため、C++26では、定数値のみ、かつ`mutable`に保持しない[`std::initializer_list`](/reference/initializer_list/initializer_list.md)は、静的記憶域に配置されるようになる。
32+
33+
```cpp
34+
void f(std::initializer_list<double> il);
35+
36+
void g(float x) {
37+
f({1, x, 3});
38+
39+
// 変数を含むため、静的記憶域には保持されない。
40+
// 以下と等価:
41+
// const double __a[3] = {double{1}, double{x}, double{3}};
42+
// f(std::initializer_list<double>(__a, __a+3));
43+
}
44+
45+
void h() {
46+
f({1, 2, 3});
47+
48+
// 定数のみであるため、静的記憶域に保持される。
49+
// 以下と等価:
50+
// static constexpr double __b[3] = {double{1}, double{2}, double{3}};
51+
// f(std::initializer_list<double>(__b, __b+3));
52+
}
53+
54+
struct A {
55+
mutable int i;
56+
};
57+
58+
void q(std::initializer_list<A>);
59+
60+
void r() {
61+
q({A{1}, A{2}, A{3}});
62+
63+
// mutableにするため、静的記憶域に保持される。
64+
// 以下と等価:
65+
// const A __c[3] = {A{1}, A{2}, A{3}};
66+
// q(std::initializer_list<A>(__c, __c+3));
67+
}
68+
```
69+
70+
将来的に、静的記憶域に配置される配列は、共有される可能性がある。この動作のために、共有で予期しない問題が起きる`mutable`は共有から除外される。
71+
72+
```cpp
73+
std::initializer_list<int> i1 = {1,2,3,4,5};
74+
std::initializer_list<int> i2 = {2,3,4};
75+
PERMIT(i1.begin() == i2.begin() + 1); // 将来的な動作
76+
```
77+
78+
## <a id="relative-page" href="#relative-page">関連項目</a>
79+
- [C++11 初期化子リスト](/lang/cpp11/initializer_lists.md)
80+
- [C++26 ファイルを読み込む`#embed`命令を追加](/lang/cpp26/embed.md)
81+
82+
83+
## 参照
84+
- [P2752R3 Static storage for braced initializers](http://open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2752r3.html)

0 commit comments

Comments
 (0)