Skip to content

Commit 3025ea8

Browse files
committed
P0848R3: 仕様と背景追加 #1106
1 parent 1e87d12 commit 3025ea8

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

lang/cpp20/conditionally_trivial_special_member_functions.md

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
```cpp
1313
template<typename T>
1414
struct wrap {
15+
T t;
1516

1617
// 1. 制約されたdefaultなコピーコンストラクタ
1718
wrap(const wrap&) requires std::is_trivially_copy_constructible_v<T> = default;
@@ -23,14 +24,43 @@ struct wrap {
2324
};
2425
```
2526
26-
`T`が`std::is_trivially_copy_constructible`を満たす場合、1の宣言が選択され`wrap<T>`のコピーコンストラクタは`default`実装される(2のコンストラクタが選択されることは無い)。`T`が`std::is_trivially_copy_constructible`を満たさない場合、2の宣言が選択され`wrap<T>`のコピーコンストラクタはユーザー定義される。
27+
`T`が`std::is_trivially_copy_constructible`を満たす場合、1の宣言が選択され`wrap<T>`のコピーコンストラクタは`default`実装される(2のコンストラクタが選択されることは無い)。`T`が`std::is_trivially_copy_constructible`を満たさない場合、2の宣言が選択され`wrap<T>`のコピーコンストラクタはユーザー定義される(1のコンストラクタが選択されることは無い)
2728
28-
特に、`T`がトリビアルコピー可能である場合にこの仕組みによって1のコンストラクタが選択されれば、(他の条件を満たしているものとして)`wrap<T>`もまたトリビアルコピー可能となる。
29+
特に、`T`がトリビアルコピー可能である場合にこの仕組みによって1のコンストラクタが選択されれば、(他の条件を満たしているものとして)`wrap<T>`もまたトリビアルコピー可能となる。トリビアル性に関する他の性質も同様に伝播することが可能となる。
2930
3031
## 仕様
3132
32-
(執筆中)
33+
次のいずれかの場合、2つの特殊メンバ関数は同種となる
34+
35+
1. 両方ともデフォルトコンストラクタ
36+
2. 両方ともコピー/ムーブコンストラクタであり、最初の引数型が同じ
37+
3. 両方ともコピー/ムーブ代入演算子であり、最初の引数型と参照・CV修飾が同じ
38+
39+
ある特殊メンバ関数が次の全てを満たす場合、それは資格のある(*eligible*)特殊メンバ関数となる
40+
41+
1. `delete`されていない
42+
2. 関連制約がある場合(コンセプト機能により制約がなされている場合)、それが満たされている
43+
3. 同種の特殊メンバ関数で、より制約されているものがない
44+
45+
次に、宣言されている全てのデストラクタはデストラクタ候補(*prospective destructor*)として扱われるようになる。そして、クラスの定義の最後(`};`が出現した場所と思って差し支えない)において、全てのデストラクタ候補の間で空の引数リストで呼び出す形でオーバーロード解決を実行し、そのクラスのデストラクタを選択する。
46+
47+
こうして選ばれたデストラクタの事を選択されたデストラクタ(*selected destructor*)とも呼ぶが、この選択されたデストラクタだけがそのクラスのデストラクタとなる(規格書中の他のすべての箇所で単にデストラクタ(*destructor*)と呼ばれるものは、この選択されたデストラクタの事を指す)。なお、何らかの理由でオーバーロード解決が失敗した場合、プログラムは不適格となる。
48+
49+
そして、あるクラスは次の条件を全て満たす場合にトリビアルコピー可能である
3350
51+
1. 少なくとも1つの、資格のあるコピーコンストラクタ、ムーブコンストラクタ、コピー代入演算子、またはムーブ代入演算子を持つ
52+
2. それら資格のあるコピーコンストラクタ、ムーブコンストラクタ、コピー代入演算子、ムーブ代入演算子、はそれぞれすべてトリビアルである
53+
3. トリビアルで削除されていないデストラクタ(選択されたデストラクタ)を持つ
54+
55+
また、あるクラスは次の条件をすべて満たす場合にトリビアルである
56+
57+
1. トリビアルコピー可能である
58+
2. 1つ以上の資格のあるデフォルトコンストラクタを持つ
59+
3. それらのデフォルトコンストラクタは全てトリビアルである
60+
61+
`default`宣言の扱いについては、選択されたデストラクタ以外の`default`指定されたデストラクタ候補は`delete`定義され、デストラクタ候補でも資格があるわけでもない`default`指定された特殊メンバ関数は`delete`定義される。
62+
63+
コンセプトによって制約された特殊メンバ関数があるとき、どれが使用されるか(オーバーロード解決)については通常の制約された関数と同じルールに従って選択される。そして、そのような特殊メンバ関数を持つ型のトリビアル性に関する性質については、特殊メンバ関数のオーバーロードのうち資格があるもの(デストラクタの場合は選択されたもの)によって決定される。
3464
3565
## 例
3666
@@ -57,13 +87,13 @@ int main()
5787

5888
## この機能が必要になった背景・経緯
5989

60-
(執筆中)
61-
90+
例にあるように、C++17まで、`std::optional`のようにテンプレートパラメータで指定された型の値を保持するラッパクラス型において、その指定された型のトリビアル性を伝播するためには非常に複雑な実装を必要としていた。
6291

63-
## 検討されたほかの選択肢
92+
C++20のコンセプトの導入によって、コンセプトによって特殊メンバ関数の宣言を選択することができるようになっていたものの、トリビアル性(特にトリビアルコピー可能性)の規格上の定義がそれを考慮したものになっておらず、コンセプトによる特殊メンバ関数の選択は仕様として完全なものではなかった。
6493

65-
(執筆中)
94+
この機能はそれを補うための仕組みであり、特殊メンバ関数に対するコンセプト制約自体は最初のコンセプト導入時から可能になっていたため、この機能は厳密にいえば仕様の調整のみである。
6695

96+
この機能は、C++23の`std::expceted`の実装で活用されるだろう。
6797

6898
## ## <a id="relative-page" href="#relative-page">関連項目</a>
6999

@@ -73,3 +103,4 @@ int main()
73103

74104
- [P0848R0 Conditionally Trivial Special Member Functions](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0848r0.html)
75105
- [P0848R3 Conditionally Trivial Special Member Functions](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0848r3.html)
106+
- [What is a "prospective destructor" in C++20? - stackoverflow](https://stackoverflow.com/questions/66055641/what-is-a-prospective-destructor-in-c20)

0 commit comments

Comments
 (0)