Skip to content

Commit 4c68758

Browse files
committed
<memory> : C++23対応としてallocate_at_leastを追加 (close #1053)
1 parent 192845f commit 4c68758

File tree

8 files changed

+218
-3
lines changed

8 files changed

+218
-3
lines changed

lang/cpp23.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ C++23とは、2023年中に改訂される予定の、C++バージョンの通
128128
### コンテナ
129129
- [`std::stack`](/reference/stack/stack.md)[`std::queue`](/reference/queue/queue.md)に、イテレータのペアをとるコンストラクタを追加
130130
- `auto v = std::vector(v, alloc);`のようなアロケータ引数をともなう場合のクラステンプレートのテンプレート引数推論が動作しなかったため、各コンテナクラスのコンストラクタにおけるアロケータパラメータの型を`const Allocator&`から`const` [`std::type_identity_t`](/reference/type_traits/type_identity.md)`<Allocator>&`に修正
131-
- N要素のメモリアロケート時にアロケータが実際にどれくらいのメモリを確保したかを得られるインタフェースとして、[`std::allocator`](/reference/memory/allocator.md)クラスに、[`allocate_at_least()`](/reference/memory/allocator/allocate_at_least.md.nolink)メンバ関数を追加
131+
- N要素のメモリアロケート時にアロケータが実際にどれくらいのメモリを確保したかを得られるインタフェースとして、
132+
- [`std::allocator`](/reference/memory/allocator.md)クラスに、[`allocate_at_least()`](/reference/memory/allocator/allocate_at_least.md)メンバ関数を追加
133+
- [`std::allocate_at_least()`](/reference/memory/allocate_at_least.md)関数を追加
132134
- [`std::pair`](/reference/utility/pair.md)の転送コンストラクタにデフォルトテンプレート引数を追加することで、`{}`のような型推論ができない引数を渡した場合でも完全転送が行われるよう修正
133135
- 順序付き連想コンテナの要素削除の処理について、一時オブジェクトのコストを抑える拡張が行われた
134136
- [`std::map::erase()`](/reference/map/map/erase.md)

reference/memory.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
|--------------------------------------------------|--------------------------------------------|-------|
1515
| [`allocator`](memory/allocator.md) | メモリアロケータの標準実装(class template) | |
1616
| [`allocator_traits`](memory/allocator_traits.md) | アロケータクラスへの間接的なアクセス(class template) | C++11 |
17+
| [`allocation_result`](memory/allocation_result.md) | [`allocate_at_least()`](memory/allocate_at_least.md)関数の戻り値型 | C++23 |
18+
| [`allocate_at_least`](memory/allocate_at_least.md) | 指定した要素数以上のメモリを確保する | C++23 |
1719
| [`allocator_arg_t`](memory/allocator_arg_t.md) | アロケータを引数として渡す際の、オーバーロード解決のためのタグ(class) | C++11 |
1820
| [`allocator_arg`](memory/allocator_arg_t.md) | アロケータを引数として渡す際の、オーバーロード解決のためのタグ(constant value) | C++11 |
1921
| [`uses_allocator`](memory/uses_allocator.md) |`T`がアロケータを使用するか調べる | C++11 |

reference/memory/allocate_at_least.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# alloacte_at_least
2+
* memory[meta header]
3+
* std[meta namespace]
4+
* function template[meta id-type]
5+
* cpp23[meta cpp]
6+
7+
```cpp
8+
namespace std {
9+
template <class Allocator>
10+
[[nodiscard] constexpr
11+
allocation_result<typename allocator_traits<Allocator>::pointer>
12+
allocate_at_least(Allocator& a, size_t n); // (1) C++23
13+
}
14+
```
15+
* allocation_result[link /reference/memory/allocation_result.md]
16+
* allocator_traits[link /reference/memory/allocator_traits.md]
17+
18+
## 概要
19+
指定した要素数以上のメモリを確保する。
20+
21+
多くのメモリアロケータはメモリ確保時に指定されたサイズちょうどではなく、少し大きなサイズを確保する。この関数は、確保されたメモリへのポインタに加えて、実際に確保されたメモリサイズを取得できる。
22+
23+
24+
## 戻り値
25+
式`a.allocate_at_least(n)`が妥当である場合、それを呼び出して返す。そうでなければ、`{a.allocate(n), n}`を返す。
26+
27+
28+
## 例
29+
```cpp example
30+
#include <iostream>
31+
#include <memory>
32+
33+
int main() {
34+
std::allocator<int> alloc;
35+
36+
std::allocation_result<int*> r = std::allocate_at_least(alloc, 3);
37+
std::cout << "allocation count:" << r.count
38+
<< " bytes:" << sizeof(int) * r.count
39+
<< std::endl;
40+
41+
alloc.deallocate(r.ptr, r.count);
42+
}
43+
```
44+
* std::allocate_at_least[color ff0000]
45+
* std::allocator[link /reference/memory/allocator.md]
46+
* std::allocation_result[link /reference/memory/allocation_result.md]
47+
* alloc.deallocate[link /reference/memory/allocator/deallocate.md]
48+
49+
### 出力例
50+
```
51+
allocation count:4 bytes:16
52+
```
53+
54+
## バージョン
55+
### 言語
56+
- C++23
57+
58+
### 処理系
59+
- [Clang](/implementation.md#clang): 19 [mark noimpl]
60+
- [GCC](/implementation.md#gcc): 14 [mark noimpl]
61+
- [Visual C++](/implementation.md#visual_cpp): 2022 Update 10 [mark noimpl]
62+
63+
64+
## 関連項目
65+
- [`std::allocation_result`](/reference/memory/allocation_result.md)
66+
- [`std::allocator`](allocator.md)`::`[`allocate_at_least()`](allocator/allocate_at_least.md)
67+
68+
69+
## 参照
70+
- [P0401R6 Providing size feedback in the Allocator interface](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0401r6.html)

reference/memory/allocation_result.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# allocation_result
2+
* memory[meta header]
3+
* std[meta namespace]
4+
* class[meta id-type]
5+
* cpp23[meta cpp]
6+
7+
```cpp
8+
namespace std {
9+
template <class Pointer>
10+
struct allocation_result {
11+
Pointer ptr;
12+
std::size_t count;
13+
};
14+
}
15+
```
16+
17+
## 概要
18+
`std::allocation_result`は、[`std::allocate_at_least()`](allocate_at_least.md)関数の戻り値型であり、以下の要素をもつ:
19+
20+
| 変数名 | 説明 |
21+
|---------|------|
22+
| `ptr` | 確保されたメモリの先頭を指すポインタ |
23+
| `count` | 実際に確保された要素数 |
24+
25+
26+
## バージョン
27+
### 言語
28+
- C++23
29+
30+
### 処理系
31+
- [Clang](/implementation.md#clang): 19 [mark noimpl]
32+
- [GCC](/implementation.md#gcc): 14 [mark noimpl]
33+
- [Visual C++](/implementation.md#visual_cpp): 2022 Update 10 [mark noimpl]
34+
35+
36+
## 関連項目
37+
- [`std::allocate_at_least()`](allocate_at_least.md)
38+
- [`std::allocator`](allocator.md)`::`[`allocate_at_least()`](allocator/allocate_at_least.md)
39+
40+
41+
## 参照
42+
- [P0401R6 Providing size feedback in the Allocator interface](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0401r6.html)

reference/memory/allocator.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ C++11から:
4343
| [`(destructor)`](allocator/op_destructor.md) | デストラクタ | |
4444
| [`operator=`](allocator/op_assign.md) | 代入演算子 | |
4545
| [`allocate`](allocator/allocate.md) | メモリを確保する | |
46+
| [`allocate_at_least`](allocator/allocate_at_least.md) | 指定した要素数以上のメモリを確保する | C++23 |
4647
| [`deallocate`](allocator/deallocate.md) | メモリを解放する | |
4748
| [`address`](allocator/address.md) | 変数のアドレスを取得する | C++17から非推奨<br/> C++20で削除 |
4849
| [`max_size`](allocator/max_size.md) | 一度に確保可能なメモリの最大サイズを取得する | C++17から非推奨<br/> C++20で削除 |

reference/memory/allocator/allocate.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ int main()
5959
```
6060

6161

62+
## 関連項目
63+
- [`allocate_at_least()`](allocate_at_least.md)
64+
65+
6266
## 参照
6367
- [P0174R2 Deprecating Vestigial Library Parts in C++17](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r2.html)
6468
- [P0600R1 `[[nodiscard]]` in the Library](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0600r1.pdf)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# alloacte_at_least
2+
* memory[meta header]
3+
* std[meta namespace]
4+
* allocator[meta class]
5+
* function template[meta id-type]
6+
* cpp23[meta cpp]
7+
8+
```cpp
9+
namespace std {
10+
[[nodiscard] constexpr allocation_result<T*>
11+
allocate_at_least(size_t n); // (1) C++23
12+
}
13+
```
14+
* allocation_result[link /reference/memory/allocation_result.md]
15+
16+
## 概要
17+
指定した要素数以上のメモリを確保する。
18+
19+
多くのメモリアロケータはメモリ確保時に指定されたサイズちょうどではなく、少し大きなサイズを確保する。この関数は、確保されたメモリへのポインタに加えて、実際に確保されたメモリサイズを取得できる。
20+
21+
22+
## 適格要件
23+
- 型`T`が不完全型ではないこと
24+
25+
26+
## 戻り値
27+
確保された配列の先頭要素へのポインタを`ptr`、`n`以上である実際に確保された要素数を`count`として、
28+
29+
```cpp
30+
return allocation_result<T*>{ptr, count};
31+
```
32+
* allocation_result[link /reference/memory/allocation_result.md]
33+
34+
35+
## 例外
36+
- [`std::numeric_limits`](/reference/limits/numeric_limits.md)`<`[`std::size_t`](/reference/cstddef/size_t.md)`>::`[`max()`](/reference/limits/numeric_limits/max.md) `/ sizeof(T) < n`である場合、[`std::bad_array_new_length`](/reference/new/bad_array_new_length.md)を送出する
37+
- メモリを確保できなかった場合、[`std::bad_alloc`](/reference/new/bad_alloc.md)を送出する
38+
39+
40+
## 備考
41+
- 配列のメモリは`::operator new`を呼び出すことで確保できるが、その関数がいつ・どれくらいの頻度で呼び出されるかは未規定
42+
- この関数は配列オブジェクトの生存期間を開始するが、配列要素の生存期間は開始しない
43+
44+
45+
##
46+
```cpp example
47+
#include <iostream>
48+
#include <memory>
49+
50+
int main() {
51+
std::allocator<int> alloc;
52+
53+
std::allocation_result<int*> r = alloc.allocate_at_least(3);
54+
std::cout << "allocation count:" << r.count
55+
<< " bytes:" << sizeof(int) * r.count
56+
<< std::endl;
57+
58+
alloc.deallocate(r.ptr, r.count);
59+
}
60+
```
61+
* alloc.allocate_at_least[color ff0000]
62+
* std::allocation_result[link /reference/memory/allocation_result.md]
63+
* alloc.deallocate[link /reference/memory/allocator/deallocate.md]
64+
65+
### 出力例
66+
```
67+
allocation count:4 bytes:16
68+
```
69+
70+
## バージョン
71+
### 言語
72+
- C++23
73+
74+
### 処理系
75+
- [Clang](/implementation.md#clang): 19 [mark noimpl]
76+
- [GCC](/implementation.md#gcc): 14 [mark noimpl]
77+
- [Visual C++](/implementation.md#visual_cpp): 2022 Update 10 [mark noimpl]
78+
79+
80+
## 関連項目
81+
- [`std::allocation_result`](/reference/memory/allocation_result.md)
82+
- [`std::allocate_at_least()`](/reference/memory/allocate_at_least.md)
83+
84+
85+
## 参照
86+
- [P0401R6 Providing size feedback in the Allocator interface](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0401r6.html)

reference/memory/allocator/deallocate.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ constexpr void deallocate(pointer p, size_type n); // C++20 から
1313
メモリを解放する。
1414
1515
16-
## 要件
17-
`p`は、[`allocate()`](allocate.md)によって確保されたポインタ値であること。`n`は、アロケートされた`p`のサイズと同じであること。
16+
## 事前条件
17+
- C++20まで
18+
- `p`は、[`allocate()`](allocate.md)によって確保されたポインタ値であること。`n`は、アロケートされた`p`のサイズと同じであること
19+
- C++23以降
20+
- `p`が[`allocate_at_least()`](allocate_at_least.md)によって確保されたポインタ値である場合、[`allocate_at_least()`](allocate_at_least.md)の戻り値を`ret`、その呼び出しで要求されたサイズを`req`として、
21+
- `p`は`ret.ptr`と等しいこと
22+
- `n`は`req <= n <= ret.count`となる値であること
23+
- そうでなければ、`p`は、[`allocate()`](allocate.md)によって確保されたポインタ値であること。`n`は、アロケートされた`p`のサイズと同じであること
1824
1925
2026
## 効果
@@ -51,3 +57,5 @@ int main()
5157
## 参照
5258
- [C++14 サイズ付きデアロケーション](/lang/cpp14/sized_deallocation.md)
5359
- [P0784R7 More constexpr containers](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0784r7.html)
60+
- [P0401R6 Providing size feedback in the Allocator interface](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0401r6.html)
61+
- C++23で`allocate_at_least()`関数が導入されたことにより、この関数の事前条件として、渡される値にその関数の戻り値であることも考慮された

0 commit comments

Comments
 (0)