[allocator.uses] (original) (raw)
20.2.8.1 uses_allocator trait [allocator.uses.trait]
template<class T, class Alloc> struct uses_allocator;
Remarks: Automatically detects whether T has a nested allocator_type that is convertible from Alloc.
The implementation shall provide a definition that is derived from true_type if the qualified-id T::allocator_typeis valid and denotes a type ([temp.deduct]) andis_convertible_v<Alloc, T::allocator_type> != false, otherwise it shall be derived from false_type.
A program may specialize this template to derive fromtrue_type for a program-defined type T that does not have a nestedallocator_type but nonetheless can be constructed with an allocator where either:
- the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or
- the last argument of a constructor has type Alloc.
20.2.8.2 Uses-allocator construction [allocator.uses.construction]
Uses-allocator constructionwith allocator alloc and constructor arguments args...refers to the construction of an object of type Tsuch that alloc is passed to the constructor of Tif 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<T>(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 asT(allocator_arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.
- Otherwise, if T has a constructor invocable asT(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 pairsuch 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 Tas a return value or in-place, respectively.
[Note 1:
For uses_allocator_construction_args andmake_obj_using_allocator, type Tis 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<T> is not a specialization of pair.
Returns: A tuple value determined as follows:
- If uses_allocator_v<remove_cv_t<T>, Alloc> is false andis_constructible_v<T, Args...> is true, return forward_as_tuple(std::forward<Args>(args)...).
- Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true andis_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true, returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)
- Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true andis_constructible_v<T, Args..., const Alloc&> is true, return forward_as_tuple(std::forward<Args>(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<T> is a specialization of pair.
Effects: Equivalent to:return 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)));
template<class T, class Alloc> constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
Constraints: remove_cv_t<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(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<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct, forward_as_tuple(std::forward<U>(u)), forward_as_tuple(std::forward<V>(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<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(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<T> is a specialization of pair.
Effects: Equivalent to:return uses_allocator_construction_args<T>(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<T> is a specialization of pair andremove_cvref_t<P> is not a specialization of ranges::subrange.
Effects: Equivalent to: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))));
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<T> is a specialization of pair, and either:
- remove_cvref_t<U> 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<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_));} };
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<T>(uses_allocator_construction_args<T>( alloc, std::forward<Args>(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<U>(xs)...);}, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));