20 General utilities library [utilities]

20.10 Memory [memory]

20.10.8 uses_­allocator [allocator.uses]

20.10.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.
Meets the Cpp17BinaryTypeTrait requirements ([meta.rqmts]).
The implementation shall provide a definition that is derived from true_­type if the qualified-id T​::​allocator_­type is valid and denotes a type ([temp.deduct]) and is_­convertible_­v<Alloc, T​::​allocator_­type> != false, otherwise it shall be derived from false_­type.
A program may specialize this template to derive from true_­type for a program-defined type T that does not have a nested allocator_­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.10.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 expression make_­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 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 and uninitialized_­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
:
For uses_­allocator_­construction_­args and make_­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 -> see below;
Constraints: T is not a specialization of pair.
Returns: A tuple value determined as follows:
  • If uses_­allocator_­v<T, Alloc> is false and is_­constructible_­v<T, Args...> is true, return forward_­as_­tuple(std​::​forward<Args>(args)...).
  • Otherwise, if uses_­allocator_­v<T, Alloc> is true and is_­constructible_­v<T, allocator_­arg_­t, const Alloc&, Args...> is true, return
    tuple<allocator_arg_t, const Alloc&, Args&&...>(
      allocator_arg, alloc, std::forward<Args>(args)...)
    
  • Otherwise, if uses_­allocator_­v<T, Alloc> is true and is_­constructible_­v<T, Args..., const Alloc&> is true, return forward_­as_­tuple(std​::​forward<Args>(args)..., alloc).
  • Otherwise, the program is ill-formed.
[Note
:
This definition prevents a silent failure to pass the allocator to a constructor of a type for which uses_­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 -> see below;
Constraints: T is a specialization of pair.
Effects: For T specified as pair<T1, T2>, 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 -> see below;
Constraints: 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 -> see below;
Constraints: 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, const pair<U,V>& pr) noexcept -> see below;
Constraints: 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 -> see below;
Constraints: T is a specialization of pair.
Effects: Equivalent to:
return uses_allocator_construction_args<T>(alloc, piecewise_construct,
                                           forward_as_tuple(std::move(pr).first),
                                           forward_as_tuple(std::move(pr).second));
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)...));