Files
cppdraft_translate/cppdraft/allocator/uses.md
2025-10-25 03:02:53 +03:00

14 KiB
Raw Blame History

[allocator.uses]

20 Memory management library [mem]

20.2 Memory [memory]

20.2.8 uses_allocator [allocator.uses]

20.2.8.1 uses_allocator trait [allocator.uses.trait]

🔗

template<class T, class Alloc> struct uses_allocator;

1

#

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]) 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]

1

#

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.

2

#

The following utility functions support three conventions for passing alloc to a constructor:

  • (2.1)

    If T does not use an allocator compatible with alloc, then alloc is ignored.

  • (2.2)

    Otherwise, if T has a constructor invocable as T(allocator_arg, alloc, args...) (leading-allocator convention), then uses-allocator construction chooses this constructor form.

  • (2.3)

    Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention), then uses-allocator construction chooses this constructor form.

3

#

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;

4

#

Constraints: remove_cv_t is not a specialization of pair.

5

#

Returns: A tuple value determined as follows:

  • (5.1)

    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)...).

  • (5.2)

    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)...)

  • (5.3)

    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).

  • (5.4)

    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;

6

#

Let T1 be T::first_type.

Let T2 be T::second_type.

7

#

Constraints: remove_cv_t is a specialization of pair.

8

#

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;

9

#

Constraints: remove_cv_t is a specialization of pair.

10

#

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;

11

#

Constraints: remove_cv_t is a specialization of pair.

12

#

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;

13

#

Constraints: remove_cv_t is a specialization of pair.

14

#

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;

15

#

Constraints: remove_cv_t is a specialization of pair.

16

#

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.2Header <tuple> synopsis[tuple.syn]") P> constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;

17

#

Constraints: remove_cv_t is a specialization of pair andremove_cvref_t

is not a specialization of ranges::subrange.

18

#

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;

19

#

Let FUN be the function template:template<class A, class B>void FUN(const pair<A, B>&);

20

#

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.

21

#

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_)); }};

22

#

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);

23

#

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);

24

#

Effects: Equivalent to:return apply([&]<class... U>(U&&... xs) {return construct_at(p, std::forward(xs)...); }, uses_allocator_construction_args(alloc, std::forward(args)...));