3

std::optional::emplace 文档中有一个接受的重载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 为真

我认为它可能用于 emplace 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使用第二次重载的示例。

4

1 回答 1

6

但不应该首先 emplace 重载 T& emplace( Args&&... args ); 够了吗?

这不是因为braced-init-list{1, 2, 3}没有类型。因为它没有类型,所以编译器无法推断出Args应该是什么。我们需要有一个显式地采用 a 的重载,std::initializer_list这样我们就可以避免编译器无法推断出括号初始化列表应该被认为是什么。

于 2021-06-09T15:03:31.980 回答