# std::scoped_allocator_adaptor<OuterAlloc,InnerAlloc...>::construct

< cpp‎ | memory‎ | scoped allocator adaptor

定义于头文件 `<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) | (C++20 前)
template< class T1, class T2 > void construct( std::pair<T1, T2>* p ); | (3) | (C++20 前)
template< class T1, class T2, class U, class V > void construct( std::pair<T1, T2>* p, U&& x, V&& y ); | (4) | (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) | (C++20 前)
template< class T1, class T2, class U, class V > void construct( std::pair<T1, T2>* p, std::pair<U, V>&& xy ); | (6) | (C++20 前)

用 `OuterAllocator` 与提供的构造函数参数在 `p` 所指向的分配但未初始化的存储构造对象。若对象是自身使用分配器的类型，或若它是 `std::pair` ，则下传 `InnerAllocator` 给构造的对象。

首先，调用 this->outer_allocator() 获得最外层分配器 `OUTERMOST` ，然后在此调用的结果上递归调用 `outer_allocator()` 成员函数直至抵达无这种成员函数的分配器。

定义 `OUTERMOST_ALLOC_TRAITS(x)` 为 std::allocator_traits<std::remove_reference_t<decltype(OUTERMOST(x))>>

1) 以使用分配器构造的手段在 p 所指示的未初始化内存位置，以 OUTERMOST 为分配器创建给定类型 `T` 的对象。在为 `T` 的构造函数所期待的使用分配器约定调整后，调用 OUTERMOST_ALLOC_TRAITS(*this)::construct 。

此重载仅若 `U` 不是 std::pair 的特化才参与重载决议。 | (C++20 前)
等价于
    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)...
        )
    );
| (C++20 起)

2) 首先，若 `T1` 或 `T2` 具分配器，则修改 `tuple` `x` 与 `y` 以包含适合的内层分配其，按照下列三条规则产生二个新的 `tuple` `xprime` 与 `yprime` ： 2a) 若 `T1` 不具分配器 (std::uses_allocator<T1, inner_allocator_type>::value==false ，则 `xprime` 是 std::tuple<Args1&&...>(std::move(x)) 。（亦要求 std::is_constructible<T1, Args1...>::value==true ） 2b) 若 `T1` 具分配器 (std::uses_allocator<T1, inner_allocator_type>::value==true) ，而其构造函数接收 `allocator_tag` (std::is_constructible<T1, std::allocator_arg_t, inner_allocator_type&, Args1...>::value==true) ，则 `xprime` 为
    std::tuple_cat(std::tuple<std::allocator_arg_t, inner_allocator_type&>(
                        std::allocator_arg, inner_allocator()
                   ),
                   std::tuple<Args1&&...>(std::move(x)))
2c) 若 `T1` 具分配器 (std::uses_allocator<T1, inner_allocator_type>::value==true) ，且其构造函数接收分配器为尾参数 (std::is_constructible<T1, Args1..., inner_allocator_type&>::value==true) ，则 `xprime` 为 std::tuple_cat(std::tuple<Args1&&...>(std::move(x)), std::tuple<inner_allocator_type&>(inner_allocator())) 。 应用相同规则到 `T2` 并以 `yprime` 替换 `y` 。 一旦构造了 `xprime` 与 `yprime` ，则在分配器的存储构造 `pair` `p` ，通过调用
    std::allocator_traits<O>::construct( OUTERMOST,
                                         p,
                                         std::piecewise_construct,
                                         std::move(xprime),
                                         std::move(yprime));
3) 等价于 construct(p, std::piecewise_construct, std::tuple<>(), std::tuple<>()) ，即传递 `pair` 的成员类型上的内层分配器，若它们接受。 4) 等价于
    construct(p, std::piecewise_construct, std::forward_as_tuple(std::forward<U>(x)),
                                           std::forward_as_tuple(std::forward<V>(y)))
5) 等价于
    construct(p, std::piecewise_construct, std::forward_as_tuple(xy.first),
                                           std::forward_as_tuple(xy.second))
6) 等价于
    construct(p, std::piecewise_construct,
                 std::forward_as_tuple(std::forward<U>(xy.first)),
                 std::forward_as_tuple(std::forward<V>(xy.second)))
| (C++20 前)

### 参数

p | - | 指向被分配但未初始化的存储的指针
args... | - | 传递给 `T` 的构造函数的构造函数参数
x | - | 传递给 `T1` 的构造函数的构造函数参数
y | - | 传递给 `T2` 的构造函数的构造函数参数
xy | - | 成员分别为 `T1` 与 `T2` 构造函数实参的 pair

### 返回值

（无）

### 注意

此函数为任何给予了 std::scoped_allocator_adaptor 作为分配器使用的具分配器对象，例如 std::vector 所调用（通过 std::allocator_traits ）。因为 `inner_allocator` 自身是 std::scoped_allocator_adaptor 的实例，此函数亦在具分配器对象通过此函数开始构造其自身成员时得到调用。

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 2975 | C++11 | 某些情况下 pair 构造错误地使用第一重载 | 制约为不接受 pair
P0475R1 | C++11 | pair 逐片构造可能复制参数 | 变换到引用的 tuple 以避免复制

### 参阅

construct [静态] | 在分配的存储构造对象 (函数模板)
construct (C++17 中弃用)(C++20 中移除) | 在分配的存储构造对象 (`std::allocator<T>` 的公开成员函数)