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

Posted

技术标签:

【中文标题】如何使用 std::optional<T>::emplace 的第二个重载【英文标题】:How to use second overload of std::optional<T>::emplace 【发布时间】:2021-08-26 14:38:46 【问题描述】:

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

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

前提是

std::is_constructible::value 为真

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

struct A

    int x;
    int y;
    int z;
;
int main()

    A normalA1, 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(A1, 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&amp; emplace( Args&amp;&amp;... args ); 就足够了吗? 我认为它可能对数组类型有用,但std::optional&lt;int[]&gt; xxx; 无论如何都无法编译。

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

【问题讨论】:

可能使emplace(1,2,3, allocator);optional&lt;vector&lt;int&gt;&gt; 工作。即使没有分配器参数,也需要重载。 【参考方案1】:

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

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

【讨论】:

以上是关于如何使用 std::optional<T>::emplace 的第二个重载的主要内容,如果未能解决你的问题,请参考以下文章

通过引用传递 std::optional<T> 是不是实际上保存复制?

如何在 if 语句中最好地测试和解包 std::optional

带有 std::any 和 std::optional 的 any_cast

如何优雅处理多参数返回/无参数返回——std::optional

是否有一种紧凑的方法可以使 std::optional<T>::value_or 对 T 的成员变量起作用

为啥允许将 std::optional 与值进行比较? [复制]