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_allocatoruninitialized_construct_using_allocatoruses_allocatorscoped_allocator_adaptorpolymorphic_allocatorpair