Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/scoped allocator adaptor/construct"

From cppreference.com
m (fmt: narrowing.)
m (Typo fix.)
 
(2 intermediate revisions by 2 users not shown)
Line 4: Line 4:
 
{{dcl header|scoped_allocator}}
 
{{dcl header|scoped_allocator}}
 
{{dcl|num=1|
 
{{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|
 
{{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::piecewise_construct_t,
+
                 std::tuple<Args1...> x, std::tuple<Args2...> y );
                 std::tuple<Args1...> x,
+
                std::tuple<Args2...> y );
+
 
}}
 
}}
 
{{dcl|num=3|until=c++20|
 
{{dcl|num=3|until=c++20|
Line 30: Line 28:
 
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|num=7|until=c++20|
+
{{dcl h|Helper function templates}}
template< class T1, class T2, class NonPair >
+
{{dcla|num=7|until=c++20|expos=yes|
void construct( std::pair<T1, T2>* p, NonPair&& non_pair );
+
template < class T, class... Args >
 +
std::tuple</* see below */> /*concat-args*/( std::tuple<Args...>&& tup );
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Constructs an object in allocated, but not initialized storage pointed to by {{tt|p}} using OuterAllocator and the provided constructor arguments. If the object is of type that itself uses allocators, or if it is std::pair, passes InnerAllocator down to the constructed object.
+
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.
  
First, retrieve the outermost allocator {{tti|OUTERMOST}} by calling {{c|this->outer_allocator()}}, and then calling the {{tt|outer_allocator()}} member function recursively on the result of this call until reaching an allocator that has no such member function.
+
@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.
 +
{{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.
  
Define {{tti|OUTERMOST_ALLOC_TRAITS}}{{c/core|(x)}} as {{c|std::allocator_traits<std::remove_reference_t<decltype(OUTERMOST(x))>>}}
+
{{cpp/enable if|{{tt|T}} is not a specialization of {{lc|std::pair}}}}.
 
+
@1@ Creates an object of the given type {{tt|T}} by means of [[cpp/memory/uses_allocator#Uses-allocator_construction|uses-allocator construction]] at the uninitialized memory location indicated by {{spar|p}}, using {{tti|OUTERMOST}} as the allocator. After adjustment for uses-allocator convention expected by T's constructor, calls {{c|OUTERMOST_ALLOC_TRAITS(*this)::construct}}.
+
 
+
{{rrev multi
+
|rev1=
+
@@{{cpp/enable if|{{tt|U}} is not a specialization of {{lc|std::pair}}}}.
+
|since2=c++20|rev2=
+
@@Equivalent to<br>{{c|
+
std::apply(
+
    [p,this](auto&&... newargs) {
+
        OUTERMOST_ALLOC_TRAITS(*this)::construct(
+
            OUTERMOST(*this), p, std::forward<decltype(newargs)>(newargs)...);
+
    },
+
    std::uses_allocator_construction_args(
+
        inner_allocator(),
+
        std::forward<Args>(args)...
+
    )
+
);
+
 
}}
 
}}
}}
+
{{rev|since=c++20|
 
+
Equivalent to {{box|
{{rrev|until=c++20|
+
{{c/core|std::apply}}<br>
@2@ First, if either {{tt|T1}} or {{tt|T2}} is allocator-aware, modifies the tuples {{tt|x}} and {{tt|y}} to include the appropriate inner allocator, resulting in the two new tuples {{tt|xprime}} and {{tt|yprime}}, according to the following three rules:
+
{{c/core|(}}<br>
:@2a@ if {{tt|T1}} is not allocator-aware<br>
+
{{nbspt|4}}{{c/core|[p, this](auto&&... newargs)}}<br>
({{c|1=std::uses_allocator<T1, inner_allocator_type>::value == false}}), then {{tt|xprime}} is  {{c|std::tuple<Args1&&...>(std::move(x))}}. (It is also required that {{c|1=std::is_constructible<T1, Args1...>::value == true}}).
+
{{nbspt|4}}{{c/core|{}}<br>
:@2b@ if {{tt|T1}} is allocator-aware ({{c|1=std::uses_allocator<T1, inner_allocator_type>::value == true}}), and its constructor takes an allocator tag<br>
+
{{nbspt|8}}{{rlpsi|helpers#outermost-construct}}<br>
{{c multi
+
{{nbspt|12}}{{c/core|(p, std::forward<decltype(newargs)>(newargs)...);}}<br>
|std::is_constructible<T1, std::allocator_arg_t,
+
{{nbspt|4}}{{c/core|},}}<br>
|                      inner_allocator_type&, Args1...>::value {{==}} true
+
{{nbspt|4}}{{c/core|std::uses_allocator_construction_args}}<br>
}},<br>
+
{{nbspt|8}}{{c/core|(inner_allocator(), std::forward<Args>(args)...)}}<br>
then {{tt|xprime}} is<br>
+
{{c/core|);}}
{{c multi
+
|std::tuple_cat(std::tuple<std::allocator_arg_t, inner_allocator_type&>(
+
|                    std::allocator_arg, inner_allocator()
+
|              ),
+
|              std::tuple<Args1&&...>(std::move(x)))
+
}}
+
:@2c@ if {{tt|T1}} is allocator-aware ({{c|1=std::uses_allocator<T1, inner_allocator_type>::value == true}}), and its constructor takes the allocator as the last argument<br>
+
{{c|1=std::is_constructible<T1, Args1..., inner_allocator_type&>::value == true}},<br>
+
then {{tt|xprime}} is<br>
+
{{c multi
+
|std::tuple_cat(std::tuple<Args1&&...>(std::move(x)),
+
|              std::tuple<inner_allocator_type&>(inner_allocator()))
+
 
}}.
 
}}.
@@Same rules apply to {{tt|T2}} and the replacement of {{tt|y}} with {{tt|yprime}}
 
@@Once {{tt|xprime}} and {{tt|yprime}} are constructed, constructs the pair {{tt|p}} in allocated storage by calling<br>
 
{{c multi|1=
 
|std::allocator_traits<O>::construct( OUTERMOST,
 
|                                    p,
 
|                                    std::piecewise_construct,
 
|                                    std::move(xprime),
 
|                                    std::move(yprime) );
 
 
}}
 
}}
 +
{{rev end}}
  
@3@ Equivalent to<br>
+
@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.
{{c|construct(p, std::piecewise_construct, std::tuple<>(), std::tuple<>())}},
+
that is, passes the inner allocator on to the pair's member types if they accept them.
+
  
@4@ Equivalent to<br>
+
:@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))}}}}.
{{c multi
+
|construct(p, std::piecewise_construct, std::forward_as_tuple(std::forward<U>(x)),
+
|                                       std::forward_as_tuple(std::forward<V>(y)))
+
}}
+
  
@5@ Equivalent to<br>
+
:@3@ Equivalent to {{c|construct(p, std::piecewise_construct, std::tuple<>(), std::tuple<>());}}.
{{c multi
+
|construct(p, std::piecewise_construct, std::forward_as_tuple(xy.first),
+
|                                      std::forward_as_tuple(xy.second))
+
}}
+
  
@6@ Equivalent to<br>
+
:@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:
{{c multi
+
{|class="wikitable" style="text-align: center;"
|construct(p, std::piecewise_construct,
+
!{{nbsp}}Overload{{nbsp}}
|             std::forward_as_tuple(std::forward<U>(xy.first)),
+
!{{normal|{{c|xarg}}}}
|             std::forward_as_tuple(std::forward<V>(xy.second)))
+
!{{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@ {{cpp/enable_if|given the exposition-only function template<br>
+
@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}}.
{{c multi
+
@@ Given {{c|std::uses_allocator<T, inner_allocator_type>::value}} as {{c|uses_inner}}:
|template< class A, class B >
+
* 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))}}.
|void /*deduce-as-pair*/( const std::pair<A, B>& );
+
* 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)))}}.
}},<br>
+
* 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())}}.
{{c|/*deduce-as-pair*/(non_pair)}} is ill-formed when considered as an unevaluated operand}}.<br>
+
* Otherwise, the program is ill-formed.
Equivalent to {{c|construct<T1, T2, T1, T2>(p, std::forward<NonPair>(non_pair));}}.
+
}}
+
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
 
{{par|p|pointer to allocated, but not initialized storage}}
 
{{par|p|pointer to allocated, but not initialized storage}}
{{par|args...|the constructor arguments to pass to the constructor of {{tt|T}}}}
+
{{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|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|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|xy|the pair whose two members are the constructor arguments for {{tt|T1}} and {{tt|T2}}}}
{{par|non_pair|non-{{tt|pair}} argument to convert to {{tt|pair}} for further construction}}
+
{{par|tup|the arguments to be merged}}
 
{{par end}}
 
{{par end}}
 
===Return value===
 
(none)
 
  
 
===Notes===
 
===Notes===
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}} is itself an instance 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.
+
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===
 
===Defect reports===
 
{{dr list begin}}
 
{{dr list begin}}
{{dr list item|wg=lwg|dr=2975|std=C++11|before=first overload is mistakenly used for pair construction in some cases|after=constrained to not accept pairs}}
+
{{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|paper=P0475R1|std=C++11|before=pair piecewise construction may copy the arguments|after=transformed to tuples of references to avoid copy}}
+
{{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=3525|std=C++11|before=no overload could handle non-{{tt|pair}} types convertible to {{tt|pair}}|after=reconstructing overload added}}
+
{{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}}
 
{{dr list end}}
  

Latest revision as of 16:44, 14 November 2024

 
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
 
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,

                std::tuple<Args1...> x, std::tuple<Args2...> y );
(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)
template< class T1, class T2, class U, class V >
void construct( std::pair<T1, T2>* p, const std::pair<U, V>& xy );
(5) (until C++20)
template< class T1, class T2, class U, class V >
void construct( std::pair<T1, T2>* p, std::pair<U, V>&& xy );
(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.

1) Constructs an object of type 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 T is not a specialization of std::pair.

(until C++20)

Equivalent to std::apply
(
    [p, this](auto&&... newargs)
    {
        outermost-construct
            (p, std::forward<decltype(newargs)>(newargs)...);
    },
    std::uses_allocator_construction_args
        (inner_allocator(), std::forward<Args>(args)...)
);
.

(since C++20)
2-6) Constructs a std::pair object by uses-allocator construction at the uninitialized memory location indicated by p using the outermost allocator.
2) Let xprime be 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)).
3) Equivalent to construct(p, std::piecewise_construct, std::tuple<>(), std::tuple<>());.
4-6) Equivalent to construct(p, std::piecewise_construct,
          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)
7) Merges the arguments contained in tup and additional arguments required by uses-allocator construction of an object of type T.
Given std::uses_allocator<T, inner_allocator_type>::value as uses_inner:

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 from
inner_allocator_type rvalues were checked
checks constructions from non-const
inner_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) [edit]
(until C++20)
constructs an object in allocated storage
(public member function of std::allocator<T>) [edit]