Skip to content

Commit f3c74df

Browse files
committed
Update cpp20.md
1 parent d836077 commit f3c74df

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

docs/standardization/cpp20.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,58 @@ prog.cc:27:2: warning: ignoring return value of function declared with 'nodiscar
700700
```
701701

702702

703+
### 指示付き初期化子 [(P0329R4)](https://wg21.link/P0329R4)
704+
C++20 から、集成体において、メンバ変数名を指定した初期化(指示付き初期化子を用いた初期化: "Designated Initialization" )ができるようになります。C 言語 (C99) にも同様の機能がありますが、C++20 では C99 と比較して以下のような制約が追加されています。
705+
706+
- (a) 指示子の順番はメンバの宣言順と同じである必要がある
707+
- (b) 指示付き初期化子と通常の初期化子の混在はできない
708+
- (c) 指示付き初期化は重複できない
709+
- (d) 指示付き初期化のネストはできない
710+
- (e) 配列の指示付き初期化はできない
711+
712+
また、初期化子の評価順序が左から右であることが保証されます。
713+
714+
```C++
715+
#include <string>
716+
717+
struct Point
718+
{
719+
int x, y;
720+
};
721+
722+
struct Item
723+
{
724+
std::string name;
725+
int id = -1;
726+
int count = 1;
727+
};
728+
729+
void F(Point) {}
730+
731+
int main()
732+
{
733+
Point p1 = { .x = 10, .y = 20 }; // OK
734+
Point p2{ .x = 10, .y = 20 }; // OK
735+
Point p3 = { .x = 10 }; // OK: y は 0 に初期化される
736+
Point p4 = { .y = 20 }; // OK: x は 0 に初期化される
737+
F({ .x = 10, .y = 20 }); // OK
738+
739+
//Point p4 = { .y = 20, .x = 30 }; // コンパイルエラー: (a) 指示子の順番がメンバの宣言順と異なる
740+
//Point p5 = { .x = 20, 40 }; // コンパイルエラー: (b) 指示付き初期化子と通常の初期化子は混在できない
741+
//Point p6 = { .x = 20, .x = 30, .y = 30 }; // コンパイルエラー: (c) 指示付き初期化子は重複できない
742+
743+
Item i1{ .name = "shield", .id = 30, .count = 100 }; // OK
744+
Item i2{ .id = 0 }; // OK: name は {} で初期化、count は 1 で初期化
745+
746+
//Item i3{ .pos.x = 10, .pos.y = 40 }; // コンパイルエラー: (d) 指示付き初期化のネストはできない
747+
748+
//int arr[3] = {[1] = 5}; // コンパイルエラー: (e) 配列の指示付き初期化はできない
749+
}
750+
```
751+
752+
従来までの `Point p{}`, `Item i{}` のような集成体初期化を「指示付き初期化子が 0 個の初期化」と考えると、新しい挙動も理解しやすくなります。
753+
754+
703755
## 標準ライブラリ
704756
705757
### 文字列の先頭や末尾が、ある文字列と一致するか判定 [(P0457R2)](https://wg21.link/P0457R2)
@@ -1743,3 +1795,45 @@ int main()
17431795
4
17441796
```
17451797
1798+
1799+
### 組み込み配列から `std::array` を作成する `std::to_array()` [(P0325R4)](https://wg21.link/P0325R4)
1800+
C++17 で導入された型推論ガイドによって、`std::array` で次のようなコードが書けるようになりました。
1801+
1802+
```C++
1803+
#include <array>
1804+
1805+
int main()
1806+
{
1807+
auto a = std::array{ 1, 2, 3 }; // std::array<int, 3>
1808+
}
1809+
```
1810+
1811+
しかし、`"hello"``int[4]` のような組み込み配列から `std::array<char, 6>``std::array<int, 4>` を作成する方法はありませんでした。
1812+
1813+
```C++
1814+
#include <array>
1815+
1816+
int main()
1817+
{
1818+
auto a1 = std::array{ "hello" }; // std::array<const char*, 1>
1819+
1820+
int xs[4] = { 1,2,3,4 };
1821+
auto a2 = std::array{ xs }; // std::array<int*, 1>
1822+
}
1823+
```
1824+
1825+
C++20 では、組み込み配列の左辺値または右辺値を引数にとり、値をコピー(ムーブ)して新しい `std::array` を作成する補助関数 `std::to_array()` が追加され、組み込み配列からの `std::array` の作成が簡単になりました。
1826+
1827+
```C++
1828+
#include <array>
1829+
1830+
int main()
1831+
{
1832+
auto a1 = std::to_array("hello"); // std::array<char, 6>
1833+
1834+
int xs[4] = { 1,2,3,4 };
1835+
auto a2 = std::to_array(xs); // std::array<int, 4>
1836+
1837+
auto a3 = std::to_array<long>({ 1, 2 }); // std::array<long, 2>
1838+
}
1839+
```

0 commit comments

Comments
 (0)