如何使用 std::optional<T>::emplace 的第二个重载

How to use second overload of std::optional<T>::emplace

std::optional::emplace docs 中有一个重载接受 std::initializer_list:

template< class U, class... Args >
T& emplace( std::initializer_list<U> ilist, Args&&... args );

前提是

std::is_constructible<T, std::initializer_list&, Args&&...>::value is true

我认为它可能用于放置 POD 类型,但显然这不是它的工作方式(在其他 SO 主题中解释说 emplace 函数使用 () 语法而不是{}):

struct A
{
    int x;
    int y;
    int z;
};
int main()
{
    A normalA{1, 2, 3};  // this is OK
    std::cout << std::is_constructible<A, std::initializer_list<int>&, int, int, int>::value << std::endl;  // false
    std::cout << std::is_constructible<A, std::initializer_list<int>&>::value << std::endl;  // false
    std::optional<A> optA;
    // optA.emplace({1, 2, 3});  // this is NOK
    optA.emplace(A{1, 2, 3});  // I can walk it around with copy-ctor
}

我可以编写接受 initializer_list:

的构造函数
struct B
{
    B(std::initializer_list<int> l) {/* some impl here */}
    int x;
    int y;
    int z;
};

然后像这样调用 emplace

    std::optional<B> optB;
    optB.emplace({1, 2, 3});

但不应该先 emplace 重载 T& emplace( Args&&... args ); 就足够了吗? 我认为它可能对数组类型有用,但 std::optional<int[]> xxx; 无论如何都无法编译。

能否提供一些使用第二个 std::optional::emplace 重载的示例。

but shouldn't first emplace overload T& emplace( Args&&... args ); be enough for that?

不是因为 braced-init-list,即 {1, 2, 3} 没有类型。因为它没有类型,所以编译器无法推断出 Args 应该是什么。我们需要有一个显式接受 std::initializer_list 的重载,这样我们就可以避免编译器无法推断出 braced-init-list 应该被视为什么。