C++ named requirements: Allocator
オブジェクトのアクセス/アドレッシング、割り当て/解放、および構築/破棄の戦略をカプセル化します。
ストレージの割り当てや解放が必要となる可能性があるすべての標準ライブラリコンポーネントは、 std::string 、 std::vector 、およびすべてのコンテナ ( std::array を除く (C++11以降) および std::inplace_vector (C++26以降) )から std::shared_ptr および std::function (C++17まで) まで、これらはすべて アロケータ を通じて行われます:以下の要件を満たすクラス型のオブジェクトです。
多くのアロケータ要件の実装はオプションです。なぜなら全ての AllocatorAwareContainer はアロケータに間接的に std::allocator_traits を通じてアクセスし、 std::allocator_traits がそれらの要件に対するデフォルト実装を提供するためです。
目次 |
要件
与えられた
-
T、 非const、非参照型 (C++11まで) 非constオブジェクト型 (C++11から) (C++17まで) CV修飾されないオブジェクト型 (C++17から) 、 -
A、型Tに対する アロケータ 型、 -
a
、型
Aのオブジェクト、 -
B、何らかのCV修飾されないオブジェクト型Uに対する対応する アロケータ 型(Aのリバインディングによって得られる)、 -
b
、型
Bのオブジェクト、 - p 、型 std:: allocator_traits < A > :: pointer の値( std:: allocator_traits < A > :: allocate ( ) の呼び出しによって得られる)、
- cp 、型 std:: allocator_traits < A > :: const_pointer の値( p からの変換によって得られる)、
- vp 、型 std:: allocator_traits < A > :: void_pointer の値( p からの変換によって得られる)、
- cvp 、型 std:: allocator_traits < A > :: const_void_pointer の値( cp または vp からの変換によって得られる)、
-
xp
、何らかのCV修飾されないオブジェクト型
Xへのデリファレンス可能なポインタ、 -
r
、式
*
p
によって得られる型
Tの左辺値、 - n 、型 std:: allocator_traits < A > :: size_type の値。
| 型ID | エイリアス型 | 要件 |
|---|---|---|
A::pointer
(オプション)
|
(未指定) [1] | |
A::const_pointer
(オプション)
|
(未指定) |
|
A::void_pointer
(オプション)
|
(未指定) |
|
A::const_void_pointer
(オプション)
|
(未指定) |
|
A::value_type
|
T
|
|
A::size_type
(オプション)
|
(未指定) |
|
A::difference_type
(オプション)
|
(未指定) |
|
A::template rebind<U>::other
(オプション) [2] |
B
|
|
| 式 | 戻り値の型 | 要件 |
|---|---|---|
| * p |
T&
|
|
| * cp | const T & | * cp と * p が同じオブジェクトを指す。 |
| p - > m | (そのまま) | ( * p ) . m と同じ。ただし ( * p ) . m が有効な場合。 |
| cp - > m | (そのまま) | ( * cp ) . m と同じ。ただし ( * cp ) . m が有効な場合。 |
| static_cast < A :: pointer > ( vp ) | (そのまま) | static_cast < A :: pointer > ( vp ) == p |
| static_cast < A :: const_pointer > ( cvp ) | (そのまま) | static_cast < A :: const_pointer > ( cvp ) == cp |
| std:: pointer_traits < A :: pointer > :: pointer_to ( r ) | (そのまま) |
| 式 | 戻り値の型 | 要件 |
|---|---|---|
| a. allocate ( n ) |
A::pointer
|
T[n]
型の配列オブジェクトに適したストレージを確保し、配列を作成するが、配列要素は構築しない。例外を送出する可能性がある。
n
==
0
の場合、戻り値は未規定。
|
| a. allocate ( n, cvp ) (オプション) | a. allocate ( n ) と同じだが、局所性を支援するために cvp ( nullptr または a. allocate ( ) から取得したポインタ)を未規定の方法で使用する可能性がある。 | |
| a. allocate_at_least ( n ) (オプション) (C++23以降) |
std::
allocation_result
< A :: pointer > |
T[cnt]
型の配列オブジェクトに適したストレージを確保し、配列を作成するが、配列要素は構築しない。その後
{
p, cnt
}
を返す。ここで
p
はストレージを指すポインタ、
cnt
は
n
以上である。例外を送出する可能性がある。
|
| a. deallocate ( p, n ) | (使用しない) |
p
が指すストレージを解放する。
p
は
allocate
または
allocate_at_least
(C++23以降)
への以前の呼び出しで返された値であり、
deallocate
への介在する呼び出しによって無効化されていないものでなければならない。
n
は以前に
allocate
に渡された値と一致するか、
allocate_at_least
を介して要求された要素数と返された要素数の間でなければならない(どちらかの境界と等しくてもよい)
(C++23以降)
。例外を送出しない。
|
| a. max_size ( ) (オプション) |
A::size_type
|
A :: allocate ( ) に渡すことができる最大の値。 |
| a. construct ( xp, args... ) (オプション) | (使用しない) |
以前に確保されたストレージ内の
xp
が指すアドレスに
X
型のオブジェクトを構築する。
args...
をコンストラクタ引数として使用する。
|
| a. destroy ( xp ) (オプション) | (使用しない) |
xp
が指す
X
型のオブジェクトを破棄するが、ストレージは解放しない。
|
| 式 | 戻り値型 | 要件 |
|---|---|---|
| a1 == a2 | bool |
|
| a1 ! = a2 |
|
|
| 宣言 | 効果 | 要件 |
| A a1 ( a ) |
a1
==
a
となるように
a1
をコピー構築する。
(注:すべての Allocator は CopyConstructible も満たす。) |
|
| A a1 = a | ||
| A a ( b ) |
B
(
a
)
==
b
かつ
A
(
b
)
==
a
となるように
a
を構築する。
(注:これは
rebind
によって関連するすべてのアロケータが互いのリソース(メモリプールなど)を維持することを意味する。)
|
|
| A a1 ( std :: move ( a ) ) | a の以前の値と等しくなるように a1 を構築する。 |
|
| A a1 = std :: move ( a ) | ||
| A a ( std :: move ( b ) ) | A ( b ) の以前の値と等しくなるように a を構築する。 |
|
| 型ID | エイリアス型 | 要件 |
A::is_always_equal
(オプション) |
std::true_type または std::false_type またはそれらから派生した型。 |
|
| 式 | 戻り値の型 | 説明 |
|---|---|---|
|
a.
select_on_container_copy_construction
(
)
(オプション) |
A
|
|
| 型ID | エイリアス型 | 説明 |
A::propagate_on_container_copy_assignment
(オプション) |
std::true_type または std::false_type またはそれらから派生した型 |
|
A::propagate_on_container_move_assignment
(オプション) |
|
|
A::propagate_on_container_swap
(オプション) |
|
注記:
- ↑ 詳細は以下の fancy pointers も参照のこと。
-
↑
rebindは、このアロケータがSomeAllocator<T, Args>という形式のテンプレートである場合にのみオプション( std::allocator_traits によって提供される)です。ここでArgsは0個以上の追加のテンプレート型パラメータです。
与えられた
-
x1
および
x2
、(異なる可能性もある)型
X::void_pointer、X::const_void_pointer、X::pointer、またはX::const_pointerのオブジェクト
-
その場合、
x1
と
x2
が
等価値の
ポインタ値であるとは、
x1
と
x2
の両方が、これら4つの型のみを使用した
static_cast
のシーケンスを用いて、型
X::const_pointerの対応する2つのオブジェクト px1 と px2 に明示的に変換可能であり、かつ式 px1 == px2 が true と評価される場合に限ります。
与えられた
-
w1
と
w2
、型
X::void_pointerのオブジェクト
-
次に、式
w1
==
w2
および
w1
!
=
w2
において、いずれか一方または両方のオブジェクトは、
等価な値を持つ
X::const_void_pointer型のオブジェクトで置き換えられても、セマンティクスに変化は生じない。
与えられた
-
p1
と
p2
、型
X::pointerのオブジェクト
-
次に、以下の式について
p1
==
p2
、
p1
!
=
p2
、
p1
<
p2
、
p1
<=
p2
、
p1
>=
p2
、
p1
>
p2
、
p1
-
p2
において、一方または両方のオブジェクトを
等価値を持つ
X::const_pointer型のオブジェクトで置き換えても、セマンティクスに変更は生じません。
上記の要件により、
Container
の
iterator
と
const_iterator
を比較することが可能となります。
アロケータ完全性要件
型
|
(C++17以降) |
ステートフルおよびステートレスアロケータ
すべての Allocator 型は、 stateful または stateless のいずれかです。一般的に、statefulアロケータ型は異なるメモリリソースを表す不等な値を持つことができますが、statelessアロケータ型は単一のメモリリソースを表します。
|
カスタムアロケータはステートレスである必要はないが、標準ライブラリでのステートフルアロケータの使用の可否と方法は実装定義である。不等なアロケータ値の使用は、実装がそのような使用をサポートしていない場合、実装定義の実行時エラーまたは未定義動作を引き起こす可能性がある。 |
(until C++11) |
|
カスタムアロケータは状態を含むことができる。各コンテナまたは他のアロケータ対応オブジェクトは、提供されたアロケータのインスタンスを格納し、 std::allocator_traits を通じてアロケータの置換を制御する。 |
(since C++11) |
ステートレスアロケータ型のインスタンスは常に等価として比較されます。ステートレスアロケータ型は通常、空のクラスとして実装され、 空の基底クラス最適化 に適しています。
|
メンバ型
|
(C++11以降) |
ファンシーポインタ
メンバ型
pointer
が生ポインタ型でない場合、一般的に
「ファンシーポインタ」
と呼ばれます。このようなポインタはセグメント化メモリアーキテクチャをサポートするために導入され、現在では生ポインタがアクセスする均質な仮想アドレス空間とは異なるアドレス空間に割り当てられたオブジェクトにアクセスするために使用されます。ファンシーポインタの例として、マッピングアドレス非依存ポインタ
boost::interprocess::offset_ptr
があり、これにより
std::set
のようなノードベースのデータ構造を共有メモリや、プロセスごとに異なるアドレスにマップされたメモリマップトファイルに割り当てることが可能になります。ファンシーポインタは、それらを提供したアロケータとは独立して使用できます
(クラステンプレート
std::pointer_traits
を通じて)
(C++11以降)
。
関数
std::to_address
を使用してファンシーポインタから生ポインタを取得できます。
(C++20以降)
|
標準ライブラリにおけるファンシーポインタおよびカスタマイズされたサイズ/異なる型の使用は条件付きでサポートされます。実装によっては、メンバ型
|
(C++11以前) |
Conceptクエリオブジェクト std::get_allocator の定義のために、以下の説明専用コンセプトが定義される。
説明専用コンセプト /*simple-allocator*/ は、 Allocator 要件の最小限の使用可能性制約を定義する。 |
(C++26以降) |
標準ライブラリ
以下の標準ライブラリコンポーネントは Allocator 要件を満たします:
|
デフォルトアロケータ
(クラステンプレート) |
|
|
(C++11)
|
マルチレベルコンテナ向けのマルチレベルアロケータを実装する
(クラステンプレート) |
|
(C++17)
|
構築時に指定された
std::pmr::memory_resource
に基づいて実行時ポリモーフィズムをサポートするアロケータ
(クラステンプレート) |
例
C++11アロケータの実装例を示します。
[[
nodiscard
]]
はC++20スタイルに合わせて追加されています。
#include <cstdlib> #include <iostream> #include <limits> #include <new> #include <vector> template<class T> struct Mallocator { typedef T value_type; Mallocator() = default; template<class U> constexpr Mallocator(const Mallocator <U>&) noexcept {} [[nodiscard]] T* allocate(std::size_t n) { if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) throw std::bad_array_new_length(); if (auto p = static_cast<T*>(std::malloc(n * sizeof(T)))) { report(p, n); return p; } throw std::bad_alloc(); } void deallocate(T* p, std::size_t n) noexcept { report(p, n, 0); std::free(p); } private: void report(T* p, std::size_t n, bool alloc = true) const { std::cout << (alloc ? "Alloc: " : "Dealloc: ") << sizeof(T) * n << " bytes at " << std::hex << std::showbase << reinterpret_cast<void*>(p) << std::dec << '\n'; } }; template<class T, class U> bool operator==(const Mallocator <T>&, const Mallocator <U>&) { return true; } template<class T, class U> bool operator!=(const Mallocator <T>&, const Mallocator <U>&) { return false; } int main() { std::vector<int, Mallocator<int>> v(8); v.push_back(42); }
出力例:
Alloc: 32 bytes at 0x2020c20 Alloc: 64 bytes at 0x2023c60 Dealloc: 32 bytes at 0x2020c20 Dealloc: 64 bytes at 0x2023c60
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| LWG 179 | C++98 |
pointer
と
const_pointer
が互いに比較可能であることが
要求されていなかった |
要求される |
| LWG 199 | C++98 |
a.allocate(0)
の戻り値が不明確だった
|
未規定 |
|
LWG 258
( N2436 ) |
C++98 |
アロケータ間の等価性関係が反射的、対称的、
推移的であることが要求されていなかった |
反射的、対称的、推移的であることが要求される |
| LWG 274 | C++98 |
T
がconst修飾型または参照型である可能性があり、
std::allocator
が不適格になる可能性があった
[1]
|
これらの型を禁止 |
| LWG 2016 | C++11 |
アロケータのコピー、ムーブ、スワップ操作が
使用時に例外を送出する可能性があった |
非例外送出が要求される |
| LWG 2081 |
C++98
C++11 |
アロケータがコピー代入(C++98)および
ムーブ代入(C++11)をサポートすることが要求されていなかった |
要求される |
| LWG 2108 | C++11 | アロケータがステートレスであることを示す方法がなかった |
is_always_equal
が提供される
|
| LWG 2263 | C++11 |
LWG issue 179
の解決がC++11で誤って削除され、
void_pointer
と
const_void_pointer
に一般化されていなかった
|
復元され一般化された |
| LWG 2447 | C++11 |
T
がvolatile修飾オブジェクト型である可能性があった
|
これらの型を禁止 |
| LWG 2593 | C++11 | アロケータからのムーブがその値を変更する可能性があった | 変更が禁止される |
| P0593R6 | C++98 |
allocate
が割り当てたストレージに配列オブジェクトを
作成することが要求されていなかった |
要求される |
-
↑
std::allocator
のメンバ型
referenceとconst_referenceは、それぞれT&とconst T&として定義される。