Difference between revisions of "cpp/memory/scoped allocator adaptor/construct"
m (newline before 2c) |
m (Typo fix.) |
||
(18 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
{{cpp/memory/scoped_allocator_adaptor/title|construct}} | {{cpp/memory/scoped_allocator_adaptor/title|construct}} | ||
− | {{cpp/memory/scoped_allocator_adaptor/ | + | {{cpp/memory/scoped_allocator_adaptor/navbar}} |
− | {{ | + | {{dcl begin}} |
− | {{ | + | {{dcl header|scoped_allocator}} |
− | {{ | + | {{dcl|num=1| |
− | template < class T, class... Args > | + | template< class T, class... Args > |
− | void construct( T* p, Args&&... args ) | + | void construct( T* p, Args&&... args ); |
}} | }} | ||
− | {{ | + | {{dcl|num=2|until=c++20| |
template< class T1, class T2, class... Args1, class... Args2 > | template< class T1, class T2, class... Args1, class... Args2 > | ||
− | void construct( std::pair<T1, T2>* p, | + | void construct( std::pair<T1, T2>* p, std::piecewise_construct_t, |
− | + | std::tuple<Args1...> x, std::tuple<Args2...> y ); | |
− | std::tuple<Args1...> x, | + | |
− | + | ||
}} | }} | ||
− | {{ | + | {{dcl|num=3|until=c++20| |
template< class T1, class T2 > | template< class T1, class T2 > | ||
− | void construct( std::pair<T1, T2>* p ) | + | void construct( std::pair<T1, T2>* p ); |
}} | }} | ||
− | {{ | + | {{dcl|num=4|until=c++20| |
template< class T1, class T2, class U, class V > | template< class T1, class T2, class U, class V > | ||
− | void construct( std::pair<T1, T2>* p, U&& x, V&& y ) | + | void construct( std::pair<T1, T2>* p, U&& x, V&& y ); |
}} | }} | ||
− | {{ | + | {{dcl|num=5|until=c++20| |
template< class T1, class T2, class U, class V > | template< class T1, class T2, class U, class V > | ||
− | void construct( std::pair<T1, T2>* p, const std::pair<U, V>& xy ) | + | void construct( std::pair<T1, T2>* p, const std::pair<U, V>& xy ); |
}} | }} | ||
− | {{ | + | {{dcl|num=6|until=c++20| |
template< class T1, class T2, class U, class V > | template< class T1, class T2, class U, class V > | ||
void construct( std::pair<T1, T2>* p, std::pair<U, V>&& xy ); | void construct( std::pair<T1, T2>* p, std::pair<U, V>&& xy ); | ||
}} | }} | ||
− | {{ | + | {{dcl h|Helper function templates}} |
− | + | {{dcla|num=7|until=c++20|expos=yes| | |
− | + | template < class T, class... Args > | |
− | + | std::tuple</* see below */> /*concat-args*/( std::tuple<Args...>&& tup ); | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | std:: | + | |
− | + | ||
− | + | ||
}} | }} | ||
+ | {{dcl end}} | ||
− | + | Constructs an object in allocated, but not initialized storage pointed to by {{c|p}} using the outer allocator and the provided constructor arguments. If the object is of a type that itself uses allocators{{rev inl|until=c++20|, or if it is {{lc|std::pair}}}}, passes the inner allocator down to the constructed object. | |
− | {{cpp| | + | @1@ Constructs an object of type {{tt|T}} by [[cpp/memory/uses_allocator#Uses-allocator_construction|uses-allocator construction]] at the uninitialized memory location indicated by {{c|p}} using the outermost allocator. |
− | std:: | + | {{rev begin}} |
− | + | {{rev|until=c++20| | |
− | + | Given {{c|std::uses_allocator<T, inner_allocator_type>::value}} as {{c|uses_inner}}: | |
− | + | * If {{c|uses_inner}} is {{c|false}} and {{c|std::is_constructible<T, Args...>::value}} is {{c|true}}, calls {{box|{{rlpsi|helpers#outermost-construct}}{{sep}}{{c/core|(p, std::forward<Args>(args)...)}}}}. | |
− | + | * Otherwise, if {{c|uses_inner}} and {{c multi|std::is_constructible<T, std::allocator_arg_t,| inner_allocator_type&,| Args...>::value}} are both {{c|true}}, calls {{box|{{rlpsi|helpers#outermost-construct}}{{sep}}{{c/core|(p, std::allocator_arg,}}<br>{{nbspt|20}}{{c/core|inner_allocator(),}}<br>{{nbspt|20}}{{c/core|std::forward<Args>(args)...)}}}}. | |
− | }} | + | * Otherwise, if {{c|uses_inner}} and {{c|std::is_constructible<T, Args..., inner_allocator_type&>::value}} are both {{c|true}}, calls {{box|{{rlpsi|helpers#outermost-construct}}{{sep}}{{c/core|(p, std::forward<Args>(args)..., inner_allocator())}}}}. |
+ | * Otherwise, the program is ill-formed. | ||
− | + | {{cpp/enable if|{{tt|T}} is not a specialization of {{lc|std::pair}}}}. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
}} | }} | ||
− | + | {{rev|since=c++20| | |
− | + | Equivalent to {{box| | |
− | + | {{c/core|std::apply}}<br> | |
− | + | {{c/core|(}}<br> | |
− | + | {{nbspt|4}}{{c/core|[p, this](auto&&... newargs)}}<br> | |
− | + | {{nbspt|4}}{{c/core|{}}<br> | |
− | + | {{nbspt|8}}{{rlpsi|helpers#outermost-construct}}<br> | |
− | + | {{nbspt|12}}{{c/core|(p, std::forward<decltype(newargs)>(newargs)...);}}<br> | |
− | {{ | + | {{nbspt|4}}{{c/core|},}}<br> |
− | + | {{nbspt|4}}{{c/core|std::uses_allocator_construction_args}}<br> | |
− | + | {{nbspt|8}}{{c/core|(inner_allocator(), std::forward<Args>(args)...)}}<br> | |
− | + | {{c/core|);}} | |
− | + | }}. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
}} | }} | ||
+ | {{rev end}} | ||
+ | @2-6@ Constructs a {{lc|std::pair}} object by [[cpp/memory/uses_allocator#Uses-allocator_construction|uses-allocator construction]] at the uninitialized memory location indicated by {{c|p}} using the outermost allocator. | ||
− | + | :@2@ Let {{c|xprime}} be {{box|{{tti|concat-args}}{{sep}}{{c/core|<T1>(std::move(x))}}}}, {{c|yprime}} be {{box|{{tti|concat-args}}{{sep}}{{c/core|<T2>(std::move(y))}}}}, calls {{box|{{rlpsi|helpers#outermost-construct}}{{sep}}{{c/core|(p, std::piecewise_construct, std::move(xprime), std::move(yprime))}}}}. | |
− | + | :@3@ Equivalent to {{c|construct(p, std::piecewise_construct, std::tuple<>(), std::tuple<>());}}. | |
− | {{ | + | :@4-6@ Equivalent to {{c multi|construct(p, std::piecewise_construct,| std::forward_as_tuple(xarg), std::forward_as_tuple(yarg));}}, where {{c|xarg}} and {{c|yarg}} are defined as follows: |
− | + | {|class="wikitable" style="text-align: center;" | |
− | + | !{{nbsp}}Overload{{nbsp}} | |
− | + | !{{normal|{{c|xarg}}}} | |
+ | !{{normal|{{c|yarg}}}} | ||
+ | |- | ||
+ | |{{v|4}} | ||
+ | |{{c|std::forward<U>(x)}} | ||
+ | |{{c|std::forward<V>(y)}} | ||
+ | |- | ||
+ | |{{v|5}} | ||
+ | |{{c|xy.first}} | ||
+ | |{{c|xy.second}} | ||
+ | |- | ||
+ | |{{v|6}} | ||
+ | |{{c|std::forward<U>(xy.first)}} | ||
+ | |{{c|std::forward<V>(xy.second)}} | ||
+ | |} | ||
− | + | @7@ Merges the arguments contained in {{c|tup}} and additional arguments required by [[cpp/memory/uses_allocator#Uses-allocator_construction|uses-allocator construction]] of an object of type {{tt|T}}. | |
− | + | @@ Given {{c|std::uses_allocator<T, inner_allocator_type>::value}} as {{c|uses_inner}}: | |
− | {{cpp| | + | * If {{c|uses_inner}} is {{c|false}} and {{c|std::is_constructible<T, Args...>::value}} is {{c|true}}, returns {{c|std::tuple<Args&&...>(std::move(tup))}}. |
− | + | * Otherwise, if {{c|uses_inner}} and {{c multi|std::is_constructible<T, std::allocator_arg_t,| inner_allocator_type&,| Args...>::value}} are both {{c|true}}, returns {{c multi|std::tuple_cat(std::tuple<std::allocator_arg_t, inner_allocator_type&>| (std::allocator_arg, inner_allocator()),| std::tuple<Args&&...>(std::move(tup)))}}. | |
− | + | * Otherwise, if {{c|uses_inner}} and {{c|std::is_constructible<T, Args..., inner_allocator_type&>::value}} are both {{c|true}}, returns {{c multi|std::tuple_cat(std::tuple<Args&&...>(std::move(tup)),| std::tuple<inner_allocator_type&>(inner_allocator())}}. | |
− | }} | + | * Otherwise, the program is ill-formed. |
− | + | ||
− | + | ||
− | + | ||
− | {{ | + | |
− | + | ||
− | + | ||
− | }} | + | |
===Parameters=== | ===Parameters=== | ||
− | {{ | + | {{par begin}} |
− | {{ | + | {{par|p|pointer to allocated, but not initialized storage}} |
− | {{ | + | {{par|args|the constructor arguments to pass to the constructor of {{tt|T}}}} |
− | {{ | + | {{par|x|the constructor arguments to pass to the constructor of {{tt|T1}}}} |
− | {{ | + | {{par|y|the constructor arguments to pass to the constructor of {{tt|T2}}}} |
− | {{ | + | {{par|xy|the pair whose two members are the constructor arguments for {{tt|T1}} and {{tt|T2}}}} |
− | {{ | + | {{par|tup|the arguments to be merged}} |
− | + | {{par end}} | |
− | + | ||
− | + | ||
===Notes=== | ===Notes=== | ||
− | This function is called (through {{ | + | This function is called (through {{lc|std::allocator_traits}}) by any allocator-aware object, such as {{lc|std::vector}}, that was given a {{lc|std::scoped_allocator_adaptor}} as the allocator to use. Since {{tt|inner_allocator_type}} is itself a specialization of {{lc|std::scoped_allocator_adaptor}}, this function will also be called when the allocator-aware objects constructed through this function start constructing their own members. |
+ | |||
+ | ===Defect reports=== | ||
+ | {{dr list begin}} | ||
+ | {{dr list item|wg=lwg|dr=2203|std=C++11|before=inner allocators were obtained by value-initializing<br>an {{tt|inner_allocator_type}} object|after=obtained by calling {{rlpf|inner_allocator}}}} | ||
+ | {{dr list item|wg=lwg|dr=2511|paper=P0475R1|std=C++11|before={{tti|concat-args}} might copy elements of {{lc|std::tuple}}s|after=eliminated all element copy operations}} | ||
+ | {{dr list item|wg=lwg|dr=2586|std=C++11|before=only constructions from<br>{{tt|inner_allocator_type}} rvalues were checked|after=checks constructions from non-const<br>{{tt|inner_allocator_type}} lvalues instead}} | ||
+ | {{dr list item|wg=lwg|dr=2975|std=C++11|before=overload {{v|1}} was not constrained|after=constrained to refuse {{lc|std::pair}}}} | ||
+ | {{dr list end}} | ||
===See also=== | ===See also=== | ||
− | {{ | + | {{dsc begin}} |
− | {{ | + | {{dsc inc|cpp/memory/allocator_traits/dsc construct}} |
− | {{ | + | {{dsc inc|cpp/memory/allocator/dsc construct}} |
− | {{ | + | {{dsc end}} |
+ | |||
+ | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} |
Latest revision as of 16:44, 14 November 2024
Defined in header <scoped_allocator>
|
||
template< class T, class... Args > void construct( T* p, Args&&... args ); |
(1) | |
template< class T1, class T2, class... Args1, class... Args2 > void construct( std::pair<T1, T2>* p, std::piecewise_construct_t, |
(2) | (until C++20) |
template< class T1, class T2 > void construct( std::pair<T1, T2>* p ); |
(3) | (until C++20) |
template< class T1, class T2, class U, class V > void construct( std::pair<T1, T2>* p, U&& x, V&& y ); |
(4) | (until C++20) |
(5) | (until C++20) | |
(6) | (until C++20) | |
Helper function templates |
||
template < class T, class... Args > std::tuple</* see below */> /*concat-args*/( std::tuple<Args...>&& tup ); |
(7) | (exposition only*) (until C++20) |
Constructs an object in allocated, but not initialized storage pointed to by p using the outer allocator and the provided constructor arguments. If the object is of a type that itself uses allocators, or if it is std::pair(until C++20), passes the inner allocator down to the constructed object.
T
by uses-allocator construction at the uninitialized memory location indicated by p using the outermost allocator.
Given std::uses_allocator<T, inner_allocator_type>::value as uses_inner:
This overload participates in overload resolution only if |
(until C++20) |
Equivalent to
std::apply |
(since C++20) |
concat-args
<T1>(std::move(x)), yprime be concat-args
<T2>(std::move(y)), calls outermost-construct
(p, std::piecewise_construct, std::move(xprime), std::move(yprime)).std::forward_as_tuple(xarg), std::forward_as_tuple(yarg));, where xarg and yarg are defined as follows:
Overload | xarg | yarg |
---|---|---|
(4) | std::forward<U>(x) | std::forward<V>(y) |
(5) | xy.first | xy.second |
(6) | std::forward<U>(xy.first) | std::forward<V>(xy.second) |
T
.- If uses_inner is false and std::is_constructible<T, Args...>::value is true, returns std::tuple<Args&&...>(std::move(tup)).
- Otherwise, if uses_inner and std::is_constructible<T, std::allocator_arg_t,
inner_allocator_type&,
Args...>::value are both true, returns std::tuple_cat(std::tuple<std::allocator_arg_t, inner_allocator_type&>
(std::allocator_arg, inner_allocator()),
std::tuple<Args&&...>(std::move(tup))). - Otherwise, if uses_inner and std::is_constructible<T, Args..., inner_allocator_type&>::value are both true, returns std::tuple_cat(std::tuple<Args&&...>(std::move(tup)),
std::tuple<inner_allocator_type&>(inner_allocator()). - Otherwise, the program is ill-formed.
Contents |
[edit] Parameters
p | - | pointer to allocated, but not initialized storage |
args | - | the constructor arguments to pass to the constructor of T
|
x | - | the constructor arguments to pass to the constructor of T1
|
y | - | the constructor arguments to pass to the constructor of T2
|
xy | - | the pair whose two members are the constructor arguments for T1 and T2
|
tup | - | the arguments to be merged |
[edit] Notes
This function is called (through std::allocator_traits) by any allocator-aware object, such as std::vector, that was given a std::scoped_allocator_adaptor as the allocator to use. Since inner_allocator_type
is itself a specialization of std::scoped_allocator_adaptor, this function will also be called when the allocator-aware objects constructed through this function start constructing their own members.
[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 2203 | C++11 | inner allocators were obtained by value-initializing an inner_allocator_type object
|
obtained by calling inner_allocator()
|
LWG 2511 (P0475R1) |
C++11 | concat-args might copy elements of std::tuples
|
eliminated all element copy operations |
LWG 2586 | C++11 | only constructions frominner_allocator_type rvalues were checked
|
checks constructions from non-constinner_allocator_type lvalues instead
|
LWG 2975 | C++11 | overload (1) was not constrained | constrained to refuse std::pair |
[edit] See also
[static] |
constructs an object in the allocated storage (function template) |
(until C++20) |
constructs an object in allocated storage (public member function of std::allocator<T> )
|