Skip to content

Commit c3a3a49

Browse files
committed
C++23対応としてコンテナのアロケータ型の推論方法を見直し #1052
1 parent 760b775 commit c3a3a49

File tree

16 files changed

+188
-29
lines changed

16 files changed

+188
-29
lines changed

lang/cpp23.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ C++23とは、2023年中に改訂され、ISO/IEC 14882:2024で標準規格化
127127

128128
### コンテナ
129129
- [`std::stack`](/reference/stack/stack.md)[`std::queue`](/reference/queue/queue.md)に、イテレータのペアをとるコンストラクタを追加
130-
- `auto v = std::vector(v, alloc);`のようなアロケータ引数をともなう場合のクラステンプレートのテンプレート引数推論が動作しなかったため、各コンテナクラスのコンストラクタにおけるアロケータパラメータの型を`const Allocator&`から`const` [`std::type_identity_t`](/reference/type_traits/type_identity.md)`<Allocator>&`に修正
130+
- `auto v = std::vector(v, alloc);`のようなアロケータ引数をともなう場合のクラステンプレートのテンプレート引数推論が動作しなかったため、各コンテナクラスのコンストラクタにおけるアロケータパラメータの型を`const Allocator&`から`const` [`std::type_identity_t`](/reference/type_traits/type_identity.md)`<Allocator>&`に修正し、コンテナアダプタの推論補助の制約を修正
131131
- N要素のメモリアロケート時にアロケータが実際にどれくらいのメモリを確保したかを得られるインタフェースとして、
132132
- [`std::allocator`](/reference/memory/allocator.md)クラスに、[`allocate_at_least()`](/reference/memory/allocator/allocate_at_least.md)メンバ関数を追加
133133
- [`std::allocator_traits`](/reference/memory/allocator_traits.md)クラスに、[`allocate_at_least()`](/reference/memory/allocator_traits/allocate_at_least.md)関数を追加

reference/deque/deque/op_constructor.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ deque(InputIterator first, InputIterator last,
2626

2727
deque(const deque& x); // (6)
2828
deque(deque&& y); // (7) C++11 から
29-
deque(const deque& x, const Allocator& a); // (8) C++11 から
30-
deque(deque&& y, const Allocator& a); // (9) C++11 から
29+
deque(const deque& x, const Allocator& a); // (8) C++11
30+
deque(const deque& x,
31+
const type_identity_t<Allocator>& a); // (8) C++23
32+
33+
deque(deque&& y, const Allocator& a); // (9) C++11
34+
deque(deque&& y, const type_identity_t<Allocator>& a); // (9) C++23
3135

3236
deque(initializer_list<T> il,
3337
const Allocator& a = Allocator()); // (10) C++11 から
@@ -36,6 +40,7 @@ template <container-compatible-range<T> R>
3640
deque(from_range_t, R&& rg,
3741
const Allocator& a = Allocator()); // (11) C++23 から
3842
```
43+
* type_identity_t[link /reference/type_traits/type_identity.md]
3944
* initializer_list[link /reference/initializer_list/initializer_list.md]
4045
* from_range_t[link ../../ranges/from_range_t.md]
4146
@@ -111,6 +116,9 @@ deque(from_range_t, R&& rg,
111116
* std::scoped_allocator_adaptor[link ../../scoped_allocator/scoped_allocator_adaptor.md]
112117
* emplace_back[link ../../list/list/emplace_back.md]
113118
119+
- C++23 では、(8) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。
120+
これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `deque` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。[`type_identity_t`](/reference/type_traits/type_identity.md) で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。
121+
114122
115123
## 例
116124
```cpp example
@@ -185,3 +193,5 @@ c7 : {1 2 3 }
185193
- [LWG 2210. Missing allocator-extended constructor for allocator-aware containers](http://cplusplus.github.io/LWG/lwg-defects.html#2210)
186194
`explicit deque(size_type n)` にアロケータ引数を追加するきっかけとなったレポート
187195
なお、Discussion の例はアロケータの型が誤っているので注意
196+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
197+
- C++23でのアロケータ引数を`type_identity_t`で包む変更

reference/forward_list/forward_list/op_constructor.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ forward_list(InputIterator first,
2727
forward_list(const forward_list& x); // (6) C++11
2828
forward_list(forward_list&& x); // (7) C++11
2929

30-
forward_list(const forward_list& x, const Allocator& a); // (8) C++11
31-
forward_list(forward_list&& x, const Allocator& a); // (9) C++11
30+
forward_list(const forward_list& x, const Allocator& a); // (8) C++11
31+
forward_list(const forward_list& x,
32+
const type_identity_t<Allocator>& a); // (8) C++23
33+
34+
forward_list(forward_list&& x, const Allocator& a); // (9) C++11
35+
forward_list(forward_list&& x,
36+
const type_identity_t<Allocator>& a); // (9) C++23
3237

3338
forward_list(initializer_list<T> il,
3439
const Allocator& a = Allocator()); // (10) C++11
@@ -37,6 +42,7 @@ template <container-compatible-range<T> R>
3742
forward_list(from_range_t, R&& rg,
3843
const Allocator& a = Allocator()); // (11) C++23
3944
```
45+
* type_identity_t[link /reference/type_traits/type_identity.md]
4046
* initializer_list[link /reference/initializer_list/initializer_list.md]
4147
* from_range_t[link ../../ranges/from_range_t.md]
4248
@@ -104,6 +110,9 @@ forward_list(from_range_t, R&& rg,
104110
* std::scoped_allocator_adaptor[link ../../scoped_allocator/scoped_allocator_adaptor.md]
105111
* emplace_back[link ../../list/list/emplace_back.md]
106112
113+
- C++23 では、(8) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。
114+
これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `forward_list` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。[`type_identity_t`](/reference/type_traits/type_identity.md) で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。
115+
107116
108117
## 例
109118
```cpp example
@@ -191,3 +200,5 @@ ls7 : 1 2 3
191200
- [LWG 2210. Missing allocator-extended constructor for allocator-aware containers](http://cplusplus.github.io/LWG/lwg-defects.html#2210)
192201
`explicit forward_list(size_type n)` にアロケータ引数を追加するきっかけとなったレポート
193202
なお、Discussion の例はアロケータの型が誤っているので注意
203+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
204+
- C++23でのアロケータ引数を`type_identity_t`で包む変更

reference/list/list/op_constructor.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ list(InputIterator first, InputIterator last,
2424

2525
list(const list& x); // (6)
2626
list(list&& x); // (7) C++11 から
27-
list(const list& x, const Allocator& a); // (8) C++11 から
28-
list(list&& x, const Allocator& a); // (9) C++11 から
27+
list(const list& x, const Allocator& a); // (8) C++11
28+
list(const list& x,
29+
const type_identity_t<Allocator>& a); // (8) C++23
30+
31+
list(list&& x, const Allocator& a); // (9) C++11
32+
list(list&& x, const type_identity_t<Allocator>& a); // (9) C++23
2933

3034
list(initializer_list<T> il,
3135
const Allocator& a = Allocator()); // (10) C++11 から
@@ -34,6 +38,7 @@ template <container-compatible-range<T> R>
3438
list(from_range_t, R&& rg,
3539
const Allocator& a = Allocator()); // (11) C++23 から
3640
```
41+
* type_identity_t[link /reference/type_traits/type_identity.md]
3742
* initializer_list[link /reference/initializer_list/initializer_list.md]
3843
* from_range_t[link /reference/ranges/from_range_t.md]
3944
@@ -100,6 +105,9 @@ list オブジェクトの構築
100105
* std::scoped_allocator_adaptor[link ../../scoped_allocator/scoped_allocator_adaptor.md]
101106
* v.emplace_back[link /reference/vector/vector/emplace_back.md]
102107
108+
- C++23 では、(8) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。
109+
これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `list` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。[`type_identity_t`](/reference/type_traits/type_identity.md) で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。
110+
103111
104112
## 例
105113
```cpp example
@@ -173,3 +181,5 @@ ls7 : 1 2 3
173181
- [LWG 2210. Missing allocator-extended constructor for allocator-aware containers](http://cplusplus.github.io/LWG/lwg-defects.html#2210)
174182
`explicit list(size_type n)` にアロケータ引数を追加するきっかけとなったレポート
175183
なお、Discussion の例はアロケータの型が誤っているので注意
184+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
185+
- C++23でのアロケータ引数を`type_identity_t`で包む変更

reference/map/map/op_constructor.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ map(InputIterator first,
2828

2929
map(const map& x); // (6)
3030

31-
map(const map& x, const Allocator& alloc); // (7) C++11 から
31+
map(const map& x, const Allocator& alloc); // (7) C++11
32+
map(const map& x,
33+
const type_identity_t<Allocator>& alloc); // (7) C++23
3234

33-
map(map&& y); // (8) C++11 から
35+
map(map&& y); // (8) C++11 から
3436

35-
map(map&& y, const Allocator& alloc); // (9) C++11 から
37+
map(map&& y, const Allocator& alloc); // (9) C++11
38+
map(map&& y, const type_identity_t<Allocator>& alloc); // (9) C++23
3639

3740
map(initializer_list<value_type> init,
3841
const Compare& comp = Compare(),
@@ -50,6 +53,7 @@ template <container-compatible-range <value_type> R>
5053
map(from_range_t, R&& rg,
5154
const Allocator& alloc); // (13) C++23 から
5255
```
56+
* type_identity_t[link /reference/type_traits/type_identity.md]
5357
* initializer_list[link ../../initializer_list.md]
5458
* from_range_t[link ../../ranges/from_range_t.md]
5559
@@ -120,6 +124,9 @@ map(from_range_t, R&& rg,
120124
なお、C++14 では同様の理由で (11) の形式も新たに追加されているが、こちらは存在しなくてもエラーとはならない。
121125
(`map(init, alloc)` の形式の構築では、(11) の形式が無い場合でも (10) の形式を用いて `init` から一時 `map` が構築され、`alloc` と共に (9) の形式に引き渡される)
122126
127+
- C++23 では、(7) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。
128+
これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `map` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。[`type_identity_t`](/reference/type_traits/type_identity.md) で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。
129+
123130
## 例
124131
```cpp example
125132
#include <iostream>
@@ -167,3 +174,5 @@ Size of m2: 2
167174
- [LWG 2210. Missing allocator-extended constructor for allocator-aware containers](http://cplusplus.github.io/LWG/lwg-defects.html#2210)
168175
(5), (11) を追加するきっかけとなったレポート
169176
なお、Discussion の例はアロケータの型が誤っているので注意
177+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
178+
- C++23でのアロケータ引数を`type_identity_t`で包む変更

reference/map/multimap/op_constructor.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ multimap(InputIterator first,
2929
multimap(const multimap& x); // (6)
3030

3131
multimap(const multimap& x,
32-
const Allocator& alloc); // (7) C++11 から
32+
const Allocator& alloc); // (7) C++11
33+
multimap(const multimap& x,
34+
const type_identity_t<Allocator>& alloc); // (7) C++23
3335

34-
multimap(multimap&& y); // (8) C++11 から
36+
multimap(multimap&& y); // (8) C++11 から
3537

3638
multimap(multimap&& y,
37-
const Allocator& alloc); // (9) C++11 から
39+
const Allocator& alloc); // (9) C++11
40+
multimap(multimap&& y,
41+
const type_identity_t<Allocator>& alloc); // (9) C++23
3842

3943
multimap(initializer_list<value_type> init,
4044
const Compare& comp = Compare(),
@@ -52,6 +56,7 @@ template <container-compatible-range <value_type> R>
5256
multimap(from_range_t, R&& rg,
5357
const Allocator& alloc); // (13) C++23 から
5458
```
59+
* type_identity_t[link /reference/type_traits/type_identity.md]
5560
* initializer_list[link ../../initializer_list.md]
5661
* from_range_t[link ../../ranges/from_range_t.md]
5762
@@ -123,6 +128,9 @@ multimap(from_range_t, R&& rg,
123128
なお、C++14 では同様の理由で (11) の形式も新たに追加されているが、こちらは存在しなくてもエラーとはならない。
124129
(`multimap(init, alloc)` の形式の構築では、(11) の形式が無い場合でも (10) の形式を用いて `init` から一時 `multimap` が構築され、`alloc` と共に (9) の形式に引き渡される)
125130
131+
- C++23 では、(7) と (9) のアロケータパラメータの型が `const Allocator&` から `const type_identity_t<Allocator>&` に変更された。
132+
これは、クラステンプレートのテンプレート引数推論 (CTAD) の際に、コピー/ムーブ元の `multimap` から推論される `Allocator` と、アロケータ引数から推論される型が異なる場合に推論が失敗する問題を修正するためである。[`type_identity_t`](/reference/type_traits/type_identity.md) で包むことで、アロケータ引数が非推論コンテキストとなり、アロケータの型はコピー/ムーブ元のみから推論されるようになる。
133+
126134
127135
## 例
128136
```cpp example
@@ -170,3 +178,5 @@ Size of m2: 3
170178
- [LWG 2210. Missing allocator-extended constructor for allocator-aware containers](http://cplusplus.github.io/LWG/lwg-defects.html#2210)
171179
(5), (11) の形式を追加するきっかけとなったレポート
172180
なお、Discussion の例はアロケータの型が誤っているので注意
181+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
182+
- C++23でのアロケータ引数を`type_identity_t`で包む変更

reference/queue/priority_queue/op_deduction_guide.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ template <class Compare, class Container>
7777
- (9) : Rangeとアロケータから推論する
7878
7979
80+
## 適格要件
81+
以下のいずれかの条件を満たす場合、コンテナアダプタの推論補助はオーバーロード解決に参加しない:
82+
83+
- `InputIterator`テンプレートパラメータをもち、入力イテレータの要件を満たさない型が推論された場合
84+
- `Compare`テンプレートパラメータをもち、アロケータとして適格な型が推論された場合 (C++23)
85+
- `Container`テンプレートパラメータをもち、アロケータとして適格な型が推論された場合 (C++23)
86+
- `Container`テンプレートパラメータをもたず、`Allocator`テンプレートパラメータをもち、アロケータとして適格でない型が推論された場合 (C++23)
87+
- `Container`と`Allocator`の両方のテンプレートパラメータをもち、[`uses_allocator_v`](/reference/memory/uses_allocator.md)`<Container, Allocator>`が`false`の場合
88+
89+
8090
## 例
8191
```cpp example
8292
#include <queue>
@@ -120,3 +130,5 @@ int main()
120130

121131
## 参照
122132
- [P0433R2 Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0433r2.html)
133+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
134+
- C++23での推論補助の制約についての変更

reference/queue/queue/op_deduction_guide.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ namespace std {
5151
- (6) : Rangeとアロケータからの推論する。
5252
5353
54+
## 適格要件
55+
以下のいずれかの条件を満たす場合、コンテナアダプタの推論補助はオーバーロード解決に参加しない:
56+
57+
- `InputIterator`テンプレートパラメータをもち、入力イテレータの要件を満たさない型が推論された場合
58+
- `Container`テンプレートパラメータをもち、アロケータとして適格な型が推論された場合 (C++23)
59+
- `Container`テンプレートパラメータをもたず、`Allocator`テンプレートパラメータをもち、アロケータとして適格でない型が推論された場合 (C++23)
60+
- `Container`と`Allocator`の両方のテンプレートパラメータをもち、[`uses_allocator_v`](/reference/memory/uses_allocator.md)`<Container, Allocator>`が`false`の場合
61+
62+
5463
## 例
5564
```cpp example
5665
#include <iostream>
@@ -104,3 +113,5 @@ int main()
104113
- [P0433R2 Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0433r2.html)
105114
- [P1425R4 Iterators pair constructors for stack and queue](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1425r4.pdf)
106115
- C++23でのイテレータペアへの対応
116+
- [P1518R2 Stop Overconstraining Allocators in Container Deduction Guides](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1518r2.html)
117+
- C++23での推論補助の制約についての変更

0 commit comments

Comments
 (0)