template <class T, class Alloc, class... Args>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
Args&&... args) -> see below; // (1) C++20
template <class T, class Alloc, class Tuple1, class Tuple2>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
piecewise_construct_t,
Tuple1&& x,
Tuple2&& y) -> see below; // (2) C++20
template <class T, class Alloc>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc) -> see below; // (3) C++20
template <class T, class Alloc, class U, class V>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
U&& u,
V&& v) -> see below; // (4) C++20
template <class T, class Alloc, class U, class V>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
pair<U,V>& pr) noexcept; // (5) C++23
template <class T, class Alloc, class U, class V>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
const pair<U, V>& pr) -> see below; // (6) C++20
template <class T, class Alloc, class U, class V>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
pair<U, V>&& pr) -> see below; // (7) C++20
template <class T, class Alloc, class U, class V>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
const pair<U,V>&& pr) noexcept; // (8) C++23
template <class T, class Alloc, pair-like P>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
P&& p) noexcept; // (9) C++23
template <class T, class Alloc, class U>
constexpr auto
uses_allocator_construction_args(
const Alloc& alloc,
U&& u) noexcept; // (10) C++23
概要
Alloc
型のアロケータオブジェクト alloc
を使用した T
型オブジェクトの uses-allocator 構築のために必要なコンストラクタ引数を、tuple
型にして返す。
また、T
が pair
だった場合は、それぞれの要素に対して uses-allocator 構築するために必要なコンストラクタ引数を、tuple
型にして返す。
構築対象の型 T
は関数引数からは推論できないため、明示的に指定する必要がある。
テンプレートパラメータ制約
- (1) :
T
がpair
の特殊化ではない場合のみオーバーロード解決に参加する - (2)-(10) :
T
がpair
の特殊化である場合のみオーバーロード解決に参加する - (9) :
P
がstd::ranges::subrange
の特殊化である場合のみオーバーロード解決に参加する - (10) : 以下のいずれかを満たす場合のみオーバーロード解決に参加する
P
がstd::ranges::subrange
の特殊化であること。もしくはU
がpair-like
の要件を満たさず、関数template<class A, class B> void FUN (const pair<A, B>&);
にFUN(u)
した場合に適格ではないこと
戻り値
-
(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), (6) : 以下と等価
uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second))
-
(7), (8) : 以下と等価
uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::move(pr).first), forward_as_tuple(std::move(pr).second))
-
(9) : 以下と等価
return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(get<0>(std::forward<P>(p))), forward_as_tuple(get<1>(std::forward<P>(p))));
-
(10) : 以下の説明用クラスを定義し、
class pair-constructor { using pair-type = remove_cv_t<T>; constexpr auto do-construct(const pair-type& p) const { return make_obj_using_allocator<pair-type>(alloc_, p); } constexpr auto do-construct(pair-type&& p) const { return make_obj_using_allocator<pair-type>(alloc_, std::move(p)); } const Alloc& alloc_; U& u_; public: constexpr operator pair-type() const { return do-construct(std::forward<U>(u_)); } };
u
でu_
、alloc
でalloc_
初期化したpair-constructor
オブジェクトpc
を生成し、make_tuple(pc)
を返す
備考
- 本関数は、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