template<class T, class Alloc, class... Args>
auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) -> see below; // (1)
template<class T, class Alloc, class Tuple1, class Tuple2>
auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t,
Tuple1&& x, Tuple2&& y) -> see below; // (2)
template<class T, class Alloc>
auto uses_allocator_construction_args(const Alloc& alloc) -> see below; // (3)
template<class T, class Alloc, class U, class V>
auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) -> see below; // (4)
template<class T, class Alloc, class U, class V>
auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) -> see below; // (5)
template<class T, class Alloc, class U, class V>
auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) -> see below; // (6)
概要
Alloc
型のアロケータオブジェクト alloc
を使用した T
型オブジェクトの uses-allocator 構築のために必要なコンストラクタ引数を、tuple
型にして返す。
また、T
が pair
だった場合は、それぞれの要素に対して uses-allocator 構築するために必要なコンストラクタ引数を、tuple
型にして返す。
構築対象の型 T
は関数引数からは推論できないため、明示的に指定する必要がある。
テンプレートパラメータ制約
戻り値
-
(1) : 以下のいずれかと同等
-
もし
uses_allocator_v<T, Alloc>
がfalse
で、かつ、is_constructible_v<T, Args...>
がtrue
の場合、forward_as_tuple(std::forward<Args>(args)...)
-
上記以外で、もし
uses_allocator_v<T, Alloc>
がtrue
で、かつ、is_constructible_v<T, allocator_arg_t, Alloc, Args...>
がtrue
の場合、tuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)
-
上記以外で、もし
uses_allocator_v<T, Alloc>
がtrue
で、かつ、is_constructible_v<T, Args..., Alloc>
がtrue
の場合、forward_as_tuple(std::forward<Args>(args)..., alloc)
-
上記以外の場合、不適格となる。
-
-
(2) :
T
をpair<T1, T2>
とすると、以下と同等make_tuple( piecewise_construct, apply([&alloc](auto&&... args1) { return uses_allocator_construction_args<T1>( alloc, std::forward<decltype(args1)>(args1)...); }, std::forward<Tuple1>(x)), apply([&alloc](auto&&... args2) { return uses_allocator_construction_args<T2>( alloc, std::forward<decltype(args2)>(args2)...); }, std::forward<Tuple2>(y)))
-
(3) : 以下と同等
uses_allocator_construction_args<T>(alloc, piecewise_construct, tuple<>{}, tuple<>{})
-
(4) : 以下と同等
uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::forward<U>(u)), forward_as_tuple(std::forward<V>(v)))
-
(5) : 以下と同等
uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second))
-
(6) : 以下と同等
uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::move(pr).first), forward_as_tuple(std::move(pr).second))
備考
- 本関数は、uses-allocator 構築をサポートするために C++20 で導入された。
本関数を用いることで、uses-allocator 構築、特にpair
に対する特殊な uses-allocator 構築を容易にサポートすることが可能となる。
ただし、実際には構築まで実施するmake_obj_using_allocator
やuninitialized_construct_using_allocator
が存在するため、これらの関数を直接呼び出す機会はあまり多くはないだろう。 - 上記 (1) を見ればわかる通り、uses-allocator 構築は、その名前に反して必ずしもアロケータオブジェクトを使うとは限らないので注意。
(uses_allocator_v<T, Alloc>
がfalse
の場合、アロケータオブジェクトalloc
は無視される) - 上記 (2)~(6) を見ればわかる通り、
T
がpair
の場合には再帰的にuses_allocator_construction_args
を呼び出しているため、ネストしたpair
に対しても正しく uses-allocator 構築をサポートできる。
例
#include <iostream>
#include <utility>
#include <memory>
// 偽アロケータ
struct MyAlloc {};
// アロケータを使用しない偽コンテナ
struct MyContainer0 {
MyContainer0(int) noexcept {}
};
// 偽アロケータを使用する偽コンテナ(allocator_arg_t 使用)
struct MyContainer1 {
using allocator_type = MyAlloc;
MyContainer1(std::allocator_arg_t, const MyAlloc&, int) noexcept {}
};
// 偽アロケータを使用する偽コンテナ(最後の引数)
struct MyContainer2 {
using allocator_type = MyAlloc;
MyContainer2(int, const MyAlloc&) noexcept {}
};
// 偽アロケータ用挿入演算子
std::ostream& operator<<(std::ostream& os, const MyAlloc&)
{
return os << "MyAlloc";
}
// allocator_arg 用挿入演算子
std::ostream& operator<<(std::ostream& os, const std::allocator_arg_t&)
{
return os << "allocator_arg_t";
}
// piecewise_construct 用挿入演算子
std::ostream& operator<<(std::ostream& os, const std::piecewise_construct_t&)
{
return os << "piecewise_construct_t";
}
// tuple 用挿入演算子
template <typename... Ts>
std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t)
{
os << "tuple(";
std::apply([&os](const auto&... args) {
((os << args << ", "), ...);
}, t);
return os << ')';
}
int main()
{
auto a0 = std::uses_allocator_construction_args<MyContainer0>(MyAlloc{}, 0);
std::cout << a0 << '\n';
auto a1 = std::uses_allocator_construction_args<MyContainer1>(MyAlloc{}, 1);
std::cout << a1 << '\n';
auto a2 = std::uses_allocator_construction_args<MyContainer2>(MyAlloc{}, 2);
std::cout << a2 << '\n';
auto a3 = std::uses_allocator_construction_args<std::pair<MyContainer1, MyContainer2>>(MyAlloc{}, 3, 4);
std::cout << a3 << '\n';
}
出力
tuple(0, )
tuple(allocator_arg_t, MyAlloc, 1, )
tuple(2, MyAlloc, )
tuple(piecewise_construct_t, tuple(allocator_arg_t, MyAlloc, 3, ), tuple(4, MyAlloc, ), )
バージョン
言語
- C++20
処理系
- Clang: 9.0.0 ❌
- GCC: 9.1.0 ✅
- ICC: ??
- Visual C++: ??
関連項目
make_obj_using_allocator
uninitialized_construct_using_allocator
uses_allocator
scoped_allocator_adaptor
polymorphic_allocator
pair