【问题标题】:optional constructor with initializer_list带有 initializer_list 的可选构造函数
【发布时间】:2015-01-31 12:32:49
【问题描述】:

这个特殊构造函数采用初始化列表的目的是什么。有人可以举例说明这在什么时候有用吗?

template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);

上面和这个有什么不同?

template <class... Args> 
constexpr explicit optional(in_place_t, Args&&... args); 

参考:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html#optional.object.ctor

附:不确定是使用 c++14 还是 c++1z 标签。我认为应该有c++技术规范的标签

【问题讨论】:

    标签: c++ c++14 optional c++17


    【解决方案1】:

    使用两个独立构造函数的原因是允许构造将initializer_list 作为构造函数参数的对象(可选地后跟任意参数列表)。假设你有一个类型 foo,看起来像这样:

    struct foo
    {
        foo(std::initializer_list<int>) {}
    };
    

    在没有构造函数的情况下

    template <class U, class... Args>
    constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
    

    您将无法将optional 构造为

    optional<foo> o(in_place, {1, 2, 3});
    

    上面的失败是因为 braced-init-list 没有类型,所以模板参数推导失败。你必须求助于这样的东西:

    auto il = {1, 2, 3};
    optional<foo> o(in_place, il);
    

    使用接受initializer_list 参数的构造函数可以在构造optional 对象时使用更自然的语法。

    这是一个minimal example,展示了这两个构造函数的实用性。

    【讨论】:

    • 嗯。 vector.emplace_back不是同样的解释吗?
    • @balki 绝对是,这就是为什么你不能做std::vector&lt;foo&gt;().emplace_back({1,2,3})std::vector&lt;foo&gt;().emplace_back(std::initializer_list&lt;int&gt;{1,2,3}) 成功的原因。
    • 我了解技术原因。但不是为什么在某些部分特别努力支持初始化列表,而在其他部分没有。
    • @balki 我无法确定,但这可能是一个疏忽。 emplace 函数和列表初始化对于 C++11 来说都是新的,可能没有人想到这种特殊情况。还要记住,容器必须委托分配器来构建新元素。也许关于分配器的某些东西使这难以实现。或者它可能只是在等待提交新提案,因为看起来添加具有与上述类似签名的 emplace(_back) 重载将是向后兼容的更改。
    • 再想一想,initializer_list 的特殊情况只是一个不必要的 hack。如果该类型有一个接受两个initializer_lists 的构造函数,它会再次中断。 gcc.godbolt.org/z/d8gX-B
    猜你喜欢
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    • 2016-10-07
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多