namespace std {
template <class T, class Alloc>
struct uses_allocator;
template <class T, class Alloc>
inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; // C++17 から
}
概要
型 T が Alloc 型のアロケータオブジェクトを用いた uses-allocator 構築をする際に、実際にアロケータオブジェクトを使用するかを調べる。
このクラスが true_type から派生する場合、以下のいずれかの構築が可能である:
T(allocator_arg, alloc, args...)のように、第1引数にallocator_arg、第2引数にAlloc型のアロケータオブジェクトallocをとる構築。T(args..., alloc)のように、最後の引数としてAlloc型のアロケータオブジェクトallocをとる構築。
このクラスのデフォルト実装は、型 T が public なメンバ型 allocator_type を持っており、その型が Alloc から変換可能であれば true_type から派生し、そうでなければ false_type から派生する。
型 T が Alloc から変換可能なメンバ型 allocator_type を持っていないが上記いずれかの構築が可能な場合は、true_type から派生した本クラステンプレートの特殊化を提供することで、アロケータを用いた構築をサポートしていることを示すことが可能である。
uses-allocator 構築
「uses-allocator 構築」とは、型 T のオブジェクト obj を構築する際に、引数とアロケータを T のコンストラクタに適切に引き渡すような構築方法である。
アロケータのオブジェクトを alloc、型を Alloc とし、引数列を v1, v2, ..., vN、その型を V1, V2, ..., VN とすると
-
Tがアロケータを利用しない場合(uses_allocator<T, Alloc>::value == falseかつ、is_constructible<T, V1, V2, ..., VN>::value == trueならば)
obj(v1, v2, ..., vN);の形でコンストラクタを呼び出す。 -
Tがアロケータを利用し、アロケータをコンストラクタ引数の先頭で受け取る場合(uses_allocator<T, Alloc>::value == trueかつ、is_constructible<T, allocator_arg_t, Alloc, V1, V2, ..., VN>::value == trueならば)
obj(allocator_arg, alloc, v1, v2, ..., vN);の形でコンストラクタを呼び出す。 -
Tがアロケータを利用し、アロケータをコンストラクタ引数の末尾で受け取る場合(uses_allocator<T, Alloc>::value == trueかつ、is_constructible<T, V1, V2, ..., VN, Alloc>::value == trueならば)
obj(v1, v2, ..., vN, alloc);の形でコンストラクタを呼び出す。 -
それ以外の場合、要求された構築はill-formedである。
すなわち、構築したい型がアロケータを利用するならば引数とアロケータを適切な順序でコンストラクタに与えて呼び出し、利用しないならば通常のコンストラクタ呼び出しを行うような構築方法である。
更に上記に加え C++20 以降では、構築する対象の型 T が pair の特殊化だった場合には、当該 pair のそれぞれの要素に対して再帰的に上記の構築方法を適用することが規定された。
備考
- 本型トレイツは、主にスコープアロケータモデルを採用するアロケータで使用されることを意図している。
標準ライブラリでは、scoped_allocator_adaptor、polymorphic_allocatorクラステンプレートで使用されている。 - 標準ライブラリで提供されるいくつかの型は本型トレイツの特殊化を提供している。(
tuple、promise、各種コンテナアダプタ等) pairはtupleと同列の機能と考えられるが、本型トレイツの特殊化を提供していない。このため、標準ライブラリで提供されるスコープアロケータモデルを採用したアロケータでは C++17 までは独自にpairの各要素に対して uses-allocator 構築を適用している(ただし、ネストしたpairの要素に対してはアロケータは伝播されない)。
スコープアロケータモデルを採用したアロケータを自作する場合には、同様の対応を行う方が良いだろう。
なお、C++20 でpairに対する特殊対応を含めた uses-allocator 構築サポートのためのユーティリティ関数が追加されたため、以前に比べて容易に uses-allocator 構築への対応が可能となった。
例
#include <iostream>
#include <memory>
template <class T, class Allocator = std::allocator<T>>
struct X {
T x_;
Allocator alloc_;
public:
using allocator_type = Allocator;
X(std::allocator_arg_t, Allocator alloc, T x)
: alloc_(alloc), x_(x) {}
};
int main()
{
const bool result = std::uses_allocator<X<int>, std::allocator<int>>::value;
static_assert(result, "should be true");
}
出力
バージョン
言語
- C++11
処理系
- Clang: 3.0 ✅
- GCC: 4.6.4 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅
関連項目
scoped_allocator_adaptorpolymorphic_allocatortuplepromiseuses_allocator_construction_argsmake_obj_using_allocatoruninitialized_construct_using_allocator