# std::variant<Types...>::emplace

< cpp‎ | utility‎ | variant

| (1) |
template <class T, class... Args> T& emplace(Args&&... args); |  | (C++17 起) (C++20 前)
template <class T, class... Args> constexpr T& emplace(Args&&... args); |  | (C++20 起)
| (2) |
template <class T, class U, class... Args> T& emplace( std::initializer_list<U> il, Args&&... args ); |  | (C++17 起) (C++20 前)
template <class T, class U, class... Args> constexpr T& emplace( std::initializer_list<U> il, Args&&... args ); |  | (C++20 起)
| (3) |
template <std::size_t I, class... Args> std::variant_alternative_t<I, variant>& emplace( Args&&... args ); |  | (C++17 起) (C++20 前)
template <std::size_t I, class... Args> constexpr std::variant_alternative_t<I, variant>& emplace( Args&&... args ); |  | (C++20 起)
| (4) |
template <std::size_t I, class U, class... Args> std::variant_alternative_t<I, variant>& emplace( std::initializer_list<U> il, Args&&... args ); |  | (C++17 起) (C++20 前)
template <std::size_t I, class U, class... Args> constexpr std::variant_alternative_t<I, variant>& emplace( std::initializer_list<U> il, Args&&... args ); |  | (C++20 起)

在既存的 `variant` 对象中原位构造新值。

1) 等价于 emplace<I>(std::forward<Args>(args)...) ，其中 `I` 是 `T` 在 `Types...` 中的零基下标。此重载仅若 std::is_constructible_v<T, Args...> 为 true ，且 `T` 在 `Types...` 中准确出现一次才参与重载决议。
2) 等价于 emplace<I>(il, std::forward<Args>(args)...) ，其中 `I` 是 `T` 在 `Types...` 中的零基下标。此重载仅若 std::is_constructible_v<T, std::initializer_list&<U>&, Args...> 为 true ，且 `T` 在 `Types...` 中准确出现一次才参与重载决议。
3) 首先，销毁当前所含值（若存在）。然后如同以参数 std::forward<Args>(args)... 构造 `T_I` 类型值一般直接初始化所含值。若抛出异常，则 *this 可能变为因异常无值。此重载仅若 std::is_constructible_v<T_I, Args...> 为 true 才参与重载决议。若 `I` 不小于 sizeof...(Types) 则行为未定义。
4) 首先，销毁当前所含值（若存在）。然后如同以参数 il, std::forward<Args>(args)... 构造 `T_I` 类型值一般直接初始化所含值。若抛出异常，则 *this 可能变为因异常无值。此重载仅若 std::is_constructible_v<T_I, std::initializer_list<U>&, Args...> 为 true 才参与重载决议。若 `I` 不小于 sizeof...(Types) 则行为未定义。

### 参数

args | - | 构造新值时使用的构造函数参数
il | - | 构造新值时使用的 `initializer_list` 参数

### 返回值

到新的所含值的引用。

### 异常

1-4) 任何初始化所含值期间可能抛出的异常。

### 示例

    #include <iostream>
    #include <string>
    #include <variant>

    int main()
    {
        std::variant<std::string> v1;
        v1.emplace<0>("abc"); // OK
        std::cout << std::get<0>(v1) << '\n';
        v1.emplace<std::string>("def"); // OK
        std::cout << std::get<0>(v1) << '\n';

        std::variant<std::string, std::string> v2;
        v2.emplace<1>("ghi"); // OK
        std::cout << std::get<1>(v2) << '\n';
        // v2.emplace<std::string>("abc"); -> 错误
    }

输出：

    abc
    def
    ghi

### 缺陷报告

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

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
P2231R1 | C++20 | `emplace` 不是 constexpr ，而要求的操作在 C++20 中能为 constexpr | 使之为 constexpr

### 参阅

operator= | 赋值 `variant` (公开成员函数)