12 KiB
[allocator.uses.construction]
20 Memory management library [mem]
20.2 Memory [memory]
20.2.8 uses_allocator [allocator.uses]
20.2.8.2 Uses-allocator construction [allocator.uses.construction]
Uses-allocator construction with allocator alloc and constructor arguments args... refers to the construction of an object of type T such that alloc is passed to the constructor of T if T uses an allocator type compatible with alloc.
When applied to the construction of an object of type T, it is equivalent to initializing it with the value of the expressionmake_obj_using_allocator(alloc, args...), described below.
The following utility functions support three conventions for passing alloc to a constructor:
-
If T does not use an allocator compatible with alloc, then alloc is ignored.
-
Otherwise, if T has a constructor invocable as T(allocator_arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.
-
Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention), then uses-allocator construction chooses this constructor form.
The uses_allocator_construction_args function template takes an allocator and argument list and produces (as a tuple) a new argument list matching one of the above conventions.
Additionally, overloads are provided that treat specializations of pair such that uses-allocator construction is applied individually to the first and second data members.
The make_obj_using_allocator anduninitialized_construct_using_allocator function templates apply the modified constructor arguments to construct an object of type T as a return value or in-place, respectively.
[Note 1:
For uses_allocator_construction_args andmake_obj_using_allocator, type T is not deduced and must therefore be specified explicitly by the caller.
â end note]
template<class T, class Alloc, class... Args> constexpr auto uses_allocator_construction_args(const Alloc& alloc, Args&&... args) noexcept;
Constraints: remove_cv_t is not a specialization of pair.
Returns: A tuple value determined as follows:
-
If uses_allocator_v<remove_cv_t, Alloc> is false and is_constructible_v<T, Args...> is true, return forward_as_tuple(std::forward(args)...).
-
Otherwise, if uses_allocator_v<remove_cv_t, Alloc> is true and is_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward(args)...)
-
Otherwise, if uses_allocator_v<remove_cv_t, Alloc> is true and is_constructible_v<T, Args..., const Alloc&> is true, return forward_as_tuple(std::forward(args)..., alloc).
-
Otherwise, the program is ill-formed.
[Note 2:
This definition prevents a silent failure to pass the allocator to a constructor of a type for whichuses_allocator_v<T, Alloc> is true.
â end note]
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) noexcept;
Let T1 be T::first_type.
Let T2 be T::second_type.
Constraints: remove_cv_t is a specialization of pair.
Effects: Equivalent to:return make_tuple( piecewise_construct, apply([&alloc](auto&&... args1) {return uses_allocator_construction_args( alloc, std::forward<decltype(args1)>(args1)...); }, std::forward(x)), apply([&alloc](auto&&... args2) {return uses_allocator_construction_args( alloc, std::forward<decltype(args2)>(args2)...); }, std::forward(y)));
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
Constraints: remove_cv_t is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args(alloc, piecewise_construct, tuple<>{}, tuple<>{});
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept;
Constraints: remove_cv_t is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args(alloc, piecewise_construct, forward_as_tuple(std::forward(u)), forward_as_tuple(std::forward(v)));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>& pr) noexcept;
Constraints: remove_cv_t is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args(alloc, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));
template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair<U, V>&& pr) noexcept; template<class T, class Alloc, class U, class V> constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair<U, V>&& pr) noexcept;
Constraints: remove_cv_t is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args(alloc, piecewise_construct, forward_as_tuple(get<0>(std::move(pr))), forward_as_tuple(get<1>(std::move(pr))));
template<class T, class Alloc, [pair-like](tuple.syn#concept:pair-like "22.4.2 Header <tuple> synopsis [tuple.syn]") P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;
Constraints: remove_cv_t is a specialization of pair andremove_cvref_t
is not a specialization of ranges::subrange.
Effects: Equivalent to:return uses_allocator_construction_args(alloc, piecewise_construct, forward_as_tuple(get<0>(std::forward
(p))), forward_as_tuple(get<1>(std::forward
(p))));
template<class T, class Alloc, class U> constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
Let FUN be the function template:template<class A, class B>void FUN(const pair<A, B>&);
Constraints: remove_cv_t is a specialization of pair, and either:
remove_cvref_t is a specialization of ranges::subrange, or
U does not satisfy pair-like and the expression FUN(u) is not well-formed when considered as an unevaluated operand.
Let pair-constructor be an exposition-only class defined as follows:class pair-constructor {using pair-type = remove_cv_t; // exposition onlyconstexpr auto do-construct(const pair-type& p) const { // exposition onlyreturn make_obj_using_allocator<pair-type>(alloc_, p); }constexpr auto do-construct(pair-type&& p) const { // exposition onlyreturn make_obj_using_allocator<pair-type>(alloc_, std::move(p)); }const Alloc& alloc_; // exposition only U& u_; // exposition onlypublic:constexpr operator pair-type() const {return do-construct(std::forward(u_)); }};
Returns: make_tuple(pc), where pc is a pair-constructor object whose alloc_ member is initialized with alloc and whose u_ member is initialized with u.
template<class T, class Alloc, class... Args> constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
Effects: Equivalent to:return make_from_tuple(uses_allocator_construction_args( alloc, std::forward(args)...));
template<class T, class Alloc, class... Args> constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
Effects: Equivalent to:return apply([&]<class... U>(U&&... xs) {return construct_at(p, std::forward(xs)...); }, uses_allocator_construction_args(alloc, std::forward(args)...));