Difference between revisions of "cpp/memory/uses allocator construction args"
(+) |
Andreas Krug (Talk | contribs) m (., @-@ -> @,@) |
||
(15 intermediate revisions by 5 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/memory/navbar}} | {{cpp/memory/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | memory}} | + | {{dcl header|memory}} |
− | {{dcl h | T is not a specialization of std::pair }} | + | {{dcl h|{{tt|T}} is not a specialization of {{lc|std::pair}}}} |
− | {{dcl | num=1 | since=c++20 | | + | {{dcl|num=1|since=c++20| |
template< class T, class Alloc, class... Args > | template< class T, class Alloc, class... Args > | ||
− | auto uses_allocator_construction_args( const Alloc& alloc, | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
− | + | Args&&... args ) noexcept; | |
}} | }} | ||
− | {{dcl h | T is a specialization of std::pair }} | + | {{dcl h|{{tt|T}} is a specialization of {{lc|std::pair}}}} |
− | {{dcl | num=2 | since=c++20 | | + | {{dcl|num=2|since=c++20| |
template< class T, class Alloc, class Tuple1, class Tuple2 > | template< class T, class Alloc, class Tuple1, class Tuple2 > | ||
− | auto uses_allocator_construction_args( const Alloc& alloc, | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
− | + | std::piecewise_construct_t, Tuple1&& x, Tuple2&& y ) noexcept; | |
− | + | ||
}} | }} | ||
− | {{dcl | num=3 | since=c++20 | | + | {{dcl|num=3|since=c++20| |
− | template< class T > | + | template< class T, class Alloc > |
− | auto uses_allocator_construction_args( const Alloc& alloc ) | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc ) noexcept; |
}} | }} | ||
− | {{dcl | num=4 | since=c++20 | | + | {{dcl|num=4|since=c++20| |
template< class T, class Alloc, class U, class V > | template< class T, class Alloc, class U, class V > | ||
− | auto uses_allocator_construction_args( const Alloc& alloc, | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
− | + | U&& u, V&& v ) noexcept; | |
}} | }} | ||
− | {{dcl | num=5 | since=c++ | + | {{dcl|num=5|since=c++23| |
template< class T, class Alloc, class U, class V > | template< class T, class Alloc, class U, class V > | ||
− | auto uses_allocator_construction_args( const Alloc& alloc, | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
− | + | std::pair<U, V>& pr ) noexcept; | |
}} | }} | ||
− | {{dcl | num=6 | since=c++20 | | + | {{dcl|num=6|since=c++20| |
template< class T, class Alloc, class U, class V > | template< class T, class Alloc, class U, class V > | ||
− | auto uses_allocator_construction_args( const Alloc& alloc, | + | constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
− | + | const std::pair<U, V>& pr ) noexcept; | |
+ | }} | ||
+ | {{dcl|num=7|since=c++20| | ||
+ | template< class T, class Alloc, class U, class V > | ||
+ | constexpr auto uses_allocator_construction_args( const Alloc& alloc, | ||
+ | std::pair<U, V>&& pr ) noexcept; | ||
+ | }} | ||
+ | {{dcl|num=8|since=c++23| | ||
+ | template< class T, class Alloc, class U, class V > | ||
+ | constexpr auto uses_allocator_construction_args( const Alloc& alloc, | ||
+ | const std::pair<U, V>&& pr ) noexcept; | ||
+ | }} | ||
+ | {{dcl|num=9|since=c++20| | ||
+ | template< class T, class Alloc, class NonPair > | ||
+ | constexpr auto uses_allocator_construction_args( const Alloc& alloc, | ||
+ | NonPair&& non_pair ) noexcept; | ||
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
Line 39: | Line 53: | ||
Prepares the argument list needed to create an object of the given type {{tt|T}} by means of {{rlp|uses_allocator|uses-allocator construction}}. | Prepares the argument list needed to create an object of the given type {{tt|T}} by means of {{rlp|uses_allocator|uses-allocator construction}}. | ||
− | @1@ {{cpp/enable if|T is not a specialization of std::pair}}. Returns {{lc|std::tuple}} determined as follows: | + | @1@ {{cpp/enable if|{{tt|T}} is not a specialization of {{lc|std::pair}}}}. Returns {{lc|std::tuple}} determined as follows: |
− | + | <!----> | |
− | + | * If {{c|std::uses_allocator_v<T, Alloc>}} is {{c|false}} and {{c|std::is_constructible_v<T, Args...>}} is {{c|true}}, returns {{c|std::forward_as_tuple(std::forward<Args>(args)...)}}. | |
− | + | * Otherwise, if {{c|std::uses_allocator_v<T, Alloc>}} is {{c|true}} and {{c|std::is_constructible_v<T, std::allocator_arg_t, const Alloc&, Args...>}} is {{c|true}}, returns<br>{{c multi | |
− | + | |std::tuple<std::allocator_arg_t, const Alloc&, Args&&...>(std::allocator_arg, alloc, | |
− | @2@ {{cpp/enable if|T is a specialization of std::pair}}. For {{ | + | | std::forward<Args>(args)...)}}. |
+ | * Otherwise, if {{c|std::uses_allocator_v<T, Alloc>}} is {{c|true}} and {{c|std::is_constructible_v<T, Args..., const Alloc&>}} is {{c|true}}, returns {{c|std::forward_as_tuple(std::forward<Args>(args)..., alloc)}}. | ||
+ | * Otherwise, the program is ill-formed. | ||
+ | @2@ {{cpp/enable if|{{tt|T}} is a specialization of {{lc|std::pair}}}}. For {{tt|T}} that is {{c|std::pair<T1, T2>}}, equivalent to | ||
{{source|1= | {{source|1= | ||
− | return std::make_tuple( std::piecewise_construct, | + | return std::make_tuple(std::piecewise_construct, |
− | std::apply( [&alloc](auto&&... args1) { | + | std::apply([&alloc](auto&&... args1) |
− | return std::uses_allocator_construction_args<T1>( alloc, | + | { |
+ | return std::uses_allocator_construction_args<T1>(alloc, | ||
std::forward<decltype(args1)>(args1)...); | std::forward<decltype(args1)>(args1)...); | ||
− | }, std::forward<Tuple1>(x)), | + | }, std::forward<Tuple1>(x) |
− | std::apply( [&alloc](auto&&... args2) { | + | ), |
− | return std::uses_allocator_construction_args<T2>( alloc, | + | std::apply([&alloc](auto&&... args2) |
− | + | { | |
− | }, std::forward<Tuple2>(y | + | return std::uses_allocator_construction_args<T2>(alloc, |
− | ); | + | std::forward<decltype(args2)>(args2)...); |
+ | }, std::forward<Tuple2>(y) | ||
+ | ) | ||
+ | ); | ||
}} | }} | ||
− | @3@ {{cpp/enable if|T is a specialization of std::pair}}. Equivalent to | + | @3@ {{cpp/enable if|{{tt|T}} is a specialization of {{lc|std::pair}}}}. Equivalent to |
{{source|1= | {{source|1= | ||
return std::uses_allocator_construction_args<T>(alloc, | return std::uses_allocator_construction_args<T>(alloc, | ||
Line 63: | Line 84: | ||
); | ); | ||
}} | }} | ||
− | @4@ {{cpp/enable if|T is a specialization of std::pair}}. Equivalent to | + | @4@ {{cpp/enable if|{{tt|T}} is a specialization of {{lc|std::pair}}}}. Equivalent to |
{{source|1= | {{source|1= | ||
− | return std::uses_allocator_construction_args<T>( alloc, | + | return std::uses_allocator_construction_args<T>(alloc, |
std::piecewise_construct, | std::piecewise_construct, | ||
std::forward_as_tuple(std::forward<U>(u)), | std::forward_as_tuple(std::forward<U>(u)), | ||
Line 71: | Line 92: | ||
); | ); | ||
}} | }} | ||
− | @5@ {{cpp/enable if|T is a specialization of std::pair}}. Equivalent to | + | @5,6@ {{cpp/enable if|{{tt|T}} is a specialization of {{lc|std::pair}}}}. Equivalent to |
{{source|1= | {{source|1= | ||
− | return std::uses_allocator_construction_args<T>( alloc, | + | return std::uses_allocator_construction_args<T>(alloc, |
std::piecewise_construct, | std::piecewise_construct, | ||
std::forward_as_tuple(pr.first), | std::forward_as_tuple(pr.first), | ||
Line 79: | Line 100: | ||
); | ); | ||
}} | }} | ||
− | @ | + | @7,8@ {{cpp/enable if|{{tt|T}} is a specialization of {{lc|std::pair}}}}. Equivalent to |
{{source|1= | {{source|1= | ||
− | return std::uses_allocator_construction_args<T>( alloc, | + | return std::uses_allocator_construction_args<T>(alloc, |
std::piecewise_construct, | std::piecewise_construct, | ||
− | std::forward_as_tuple(std::move(pr) | + | std::forward_as_tuple(std::get<0>(std::move(pr))), |
− | std::forward_as_tuple(std::move(pr). | + | std::forward_as_tuple(std::get<1>(std::move(pr))) |
+ | ); | ||
+ | }} | ||
+ | @9@ {{cpp/enable_if|{{tt|T}} is a specialization of {{lc|std::pair}}, and given the exposition-only function template | ||
+ | {{source|template<class A, class B> | ||
+ | void /*deduce-as-pair*/(const std::pair<A, B>&); | ||
+ | }} | ||
+ | , {{c|/*deduce-as-pair*/(non_pair)}} is ill-formed when considered as an unevaluated operand}}.<br><!-- | ||
+ | -->Let the exposition-only class {{tt|''pair-constructor''}} be defined as | ||
+ | {{source|1= | ||
+ | class /*pair-constructor*/ | ||
+ | { | ||
+ | const Alloc& alloc_; // exposition only | ||
+ | NonPair& u_; // exposition only | ||
+ | |||
+ | constexpr reconstruct(const std::remove_cv<T>& p) const // exposition only | ||
+ | { | ||
+ | return std::make_obj_using_allocator<std::remove_cv<T>>(alloc_, p); | ||
+ | } | ||
+ | |||
+ | constexpr reconstruct(std::remove_cv<T>&& p) const // exposition only | ||
+ | { | ||
+ | return std::make_obj_using_allocator<std::remove_cv<T>>(alloc_, std::move(p)); | ||
+ | } | ||
+ | |||
+ | public: | ||
+ | constexpr operator std::remove_cv<T>() const | ||
+ | { | ||
+ | return reconstruct(std::forward<NonPair>(u_)); | ||
+ | } | ||
+ | }; | ||
}} | }} | ||
+ | This overload is equivalent to {{c|return std::make_tuple(pair_construction);}}, where {{tt|pair_construction}} is a value of type {{tt|''pair-constructor''}} whose {{tt|''alloc_''}} and {{tt|''u_''}} members are {{tt|alloc}} and {{tt|non_pair}} respectively. | ||
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | alloc | the allocator to use | + | {{par|alloc|the allocator to use}} |
− | {{par | args | the arguments to pass to T's constructor}} | + | {{par|args|the arguments to pass to {{tt|T}}'s constructor}} |
− | {{par | x | tuple of arguments to pass to the constructors of T's | + | {{par|x|tuple of arguments to pass to the constructors of {{tt|T}}'s {{tt|first}} data member}} |
− | {{par | y | tuple of arguments to pass to the constructors of T's | + | {{par|y|tuple of arguments to pass to the constructors of {{tt|T}}'s {{tt|second}} data member}} |
− | {{par | u | single argument to pass to the constructor of T's | + | {{par|u|single argument to pass to the constructor of {{tt|T}}'s {{tt|first}} data member}} |
− | {{par | v | single argument to pass to the constructor of T's | + | {{par|v|single argument to pass to the constructor of {{tt|T}}'s {{tt|second}} data member}} |
− | {{par | pr | a pair whose | + | {{par|pr|a pair whose {{tt|first}} data member will be passed to the constructor of {{tt|T}}'s {{tt|first}} data member and {{tt|second}} data member will be passed to the constructor of {{tt|T}}'s {{tt|second}} data member}} |
+ | {{par|non_pair|single argument to convert to a {{lc|std::pair}} for further construction}} | ||
{{par end}} | {{par end}} | ||
===Return value=== | ===Return value=== | ||
− | {{lc|std::tuple}} of arguments suitable for passing to the constructor of {{tt|T}} | + | {{lc|std::tuple}} of arguments suitable for passing to the constructor of {{tt|T}}. |
+ | |||
+ | ===Notes=== | ||
+ | The overloads {{v|2-9}} provide allocator propagation into {{lc|std::pair}}, which supports neither leading-allocator nor trailing-allocator calling conventions (unlike, e.g. {{lc|std::tuple}}, which uses leading-allocator convention). | ||
+ | |||
+ | When used in uses-allocator construction, the conversion function of {{tt|''pair-constructor''}} converts the provided argument to {{lc|std::pair}} at first, and then constructs the result from that {{lc|std::pair}} by uses-allocator construction. | ||
===Example=== | ===Example=== | ||
{{example}} | {{example}} | ||
− | === | + | ===Defect reports=== |
− | + | {{dr list begin}} | |
+ | {{dr list item|wg=lwg|dr=3525|std=C++20|before=no overload could handle non-{{tt|pair}} types convertible to {{tt|pair}}|after=reconstructing overload added}} | ||
+ | {{dr list end}} | ||
===See also=== | ===See also=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc inc | cpp/memory/dsc uses_allocator}} | + | {{dsc inc|cpp/memory/dsc uses_allocator}} |
− | {{dsc inc | cpp/memory/dsc make_obj_using_allocator}} | + | {{dsc inc|cpp/memory/dsc make_obj_using_allocator}} |
− | {{dsc inc | cpp/memory/dsc uninitialized_construct_using_allocator}} | + | {{dsc inc|cpp/memory/dsc uninitialized_construct_using_allocator}} |
{{dsc end}} | {{dsc end}} | ||
− | {{langlinks|ja|zh}} | + | {{langlinks|de|es|ja|ru|zh}} |
Latest revision as of 06:52, 8 October 2023
Defined in header <memory>
|
||
T is not a specialization of std::pair |
||
template< class T, class Alloc, class... Args > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(1) | (since C++20) |
T is a specialization of std::pair |
||
template< class T, class Alloc, class Tuple1, class Tuple2 > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(2) | (since C++20) |
template< class T, class Alloc > constexpr auto uses_allocator_construction_args( const Alloc& alloc ) noexcept; |
(3) | (since C++20) |
template< class T, class Alloc, class U, class V > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(4) | (since C++20) |
template< class T, class Alloc, class U, class V > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(5) | (since C++23) |
template< class T, class Alloc, class U, class V > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(6) | (since C++20) |
template< class T, class Alloc, class U, class V > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(7) | (since C++20) |
template< class T, class Alloc, class U, class V > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(8) | (since C++23) |
template< class T, class Alloc, class NonPair > constexpr auto uses_allocator_construction_args( const Alloc& alloc, |
(9) | (since C++20) |
Prepares the argument list needed to create an object of the given type T
by means of uses-allocator construction.
T
is not a specialization of std::pair. Returns std::tuple determined as follows:
- If std::uses_allocator_v<T, Alloc> is false and std::is_constructible_v<T, Args...> is true, returns std::forward_as_tuple(std::forward<Args>(args)...).
- Otherwise, if std::uses_allocator_v<T, Alloc> is true and std::is_constructible_v<T, std::allocator_arg_t, const Alloc&, Args...> is true, returns
std::tuple<std::allocator_arg_t, const Alloc&, Args&&...>(std::allocator_arg, alloc,
std::forward<Args>(args)...). - Otherwise, if std::uses_allocator_v<T, Alloc> is true and std::is_constructible_v<T, Args..., const Alloc&> is true, returns std::forward_as_tuple(std::forward<Args>(args)..., alloc).
- Otherwise, the program is ill-formed.
T
is a specialization of std::pair. For T
that is std::pair<T1, T2>, equivalent to
return std::make_tuple(std::piecewise_construct, std::apply([&alloc](auto&&... args1) { return std::uses_allocator_construction_args<T1>(alloc, std::forward<decltype(args1)>(args1)...); }, std::forward<Tuple1>(x) ), std::apply([&alloc](auto&&... args2) { return std::uses_allocator_construction_args<T2>(alloc, std::forward<decltype(args2)>(args2)...); }, std::forward<Tuple2>(y) ) );
T
is a specialization of std::pair. Equivalent to
return std::uses_allocator_construction_args<T>(alloc, std::piecewise_construct, std::tuple<>{}, std::tuple<>{} );
T
is a specialization of std::pair. Equivalent to
return std::uses_allocator_construction_args<T>(alloc, std::piecewise_construct, std::forward_as_tuple(std::forward<U>(u)), std::forward_as_tuple(std::forward<V>(v)) );
T
is a specialization of std::pair. Equivalent to
return std::uses_allocator_construction_args<T>(alloc, std::piecewise_construct, std::forward_as_tuple(pr.first), std::forward_as_tuple(pr.second) );
T
is a specialization of std::pair. Equivalent to
return std::uses_allocator_construction_args<T>(alloc, std::piecewise_construct, std::forward_as_tuple(std::get<0>(std::move(pr))), std::forward_as_tuple(std::get<1>(std::move(pr))) );
T
is a specialization of std::pair, and given the exposition-only function template
template<class A, class B> void /*deduce-as-pair*/(const std::pair<A, B>&);
, /*deduce-as-pair*/(non_pair) is ill-formed when considered as an unevaluated operand.
Let the exposition-only class pair-constructor
be defined as
class /*pair-constructor*/ { const Alloc& alloc_; // exposition only NonPair& u_; // exposition only constexpr reconstruct(const std::remove_cv<T>& p) const // exposition only { return std::make_obj_using_allocator<std::remove_cv<T>>(alloc_, p); } constexpr reconstruct(std::remove_cv<T>&& p) const // exposition only { return std::make_obj_using_allocator<std::remove_cv<T>>(alloc_, std::move(p)); } public: constexpr operator std::remove_cv<T>() const { return reconstruct(std::forward<NonPair>(u_)); } };
pair_construction
is a value of type pair-constructor
whose alloc_
and u_
members are alloc
and non_pair
respectively.Contents |
[edit] Parameters
alloc | - | the allocator to use |
args | - | the arguments to pass to T 's constructor
|
x | - | tuple of arguments to pass to the constructors of T 's first data member
|
y | - | tuple of arguments to pass to the constructors of T 's second data member
|
u | - | single argument to pass to the constructor of T 's first data member
|
v | - | single argument to pass to the constructor of T 's second data member
|
pr | - | a pair whose first data member will be passed to the constructor of T 's first data member and second data member will be passed to the constructor of T 's second data member
|
non_pair | - | single argument to convert to a std::pair for further construction |
[edit] Return value
std::tuple of arguments suitable for passing to the constructor of T
.
[edit] Notes
The overloads (2-9) provide allocator propagation into std::pair, which supports neither leading-allocator nor trailing-allocator calling conventions (unlike, e.g. std::tuple, which uses leading-allocator convention).
When used in uses-allocator construction, the conversion function of pair-constructor
converts the provided argument to std::pair at first, and then constructs the result from that std::pair by uses-allocator construction.
[edit] Example
This section is incomplete Reason: no example |
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 3525 | C++20 | no overload could handle non-pair types convertible to pair
|
reconstructing overload added |
[edit] See also
(C++11) |
checks if the specified type supports uses-allocator construction (class template) |
(C++20) |
creates an object of the given type by means of uses-allocator construction (function template) |
creates an object of the given type at specified memory location by means of uses-allocator construction (function template) |