为什么我不能构造带有可选<s>的可选<t>(对于S!= T)?

时间:2016-05-02 12:58:38

标签: c++ optional c++-standard-library c++17

如果我们有

 std::experimental::optional<int> x;

以下两行都没有编译:

 std::experimental::optional<unsigned int> y; y = x;
 std::experimental::optional<unsigned int> z(x);

...即使在我看来有意义,就像将int分配给unsigned int一样。为什么不能这样做?也就是说,库没有为这种情况实现复制ctor和赋值运算符而避免的陷阱是什么?

3 个答案:

答案 0 :(得分:4)

你不能这样做,因为std::experimental::optional对于构造函数和赋值运算符没有适当的重载。

肯定可以提供这样的界面。事实上,提出的接口所基于的boost optional确实有一个重载的构造函数和赋值运算符,用于从另一个optional实例构造。

proposal有一节“与Boost.Optional比较”,其中包含一个包含讨论过载的比较表。除了一般性陈述之外,该提案没有给出差异的理由:

  

目前的提案反映了我们在界面的明确性,通用性和灵活性之间任意选择平衡。

具有参考实现的git repoISO C++ Standard - Future Proposals邮件列表中讨论了是否包含重载的基本原理。

在github问题中,该提案的作者AndrzejKrzemieński表明了这种过载可能导致的问题模糊:

  

目前尚不清楚在以下情况下会发生什么:

struct Tool
{
  Tool(int); // ctor 1
  Tool(optional<int>); // ctor 2
};

optional<int> oi = 1;
optional<Tool> ot = oi;
     

应该调用Tool的哪个构造函数以及为什么?

答案 1 :(得分:3)

这里似乎是反对转换建构的基本论点(作者姓名不清楚,但它来自this thread):

  

我们有两个构造函数:

     
      来自optional<T>
  • 取消装箱optional<U>,如果已初始化可选项,则T构建U
  •   
  • 转发:来自U的可选项,可从T构建U
  •   
     

问题是,如果TU同时构建optional<U>,我们就会有歧义,现在我们可以   选择3中的一个:

     
      
  1. 编译错误,让程序员决定
  2.   
  3. 首选取消装箱构造函数
  4.   
  5. 首选转发构造函数
  6.   

我真的认为这根本不是什么问题,但我不会在这里开始讨论。

答案 2 :(得分:2)

n3672提案与Boost.Optional进行比较。其中一个主要差异是std::optional不允许从optional<U>转换为optional<T>std::optionalBoost.Optional之后({1}}重复建模{至少1.48.0,不知道自那以后发生了什么变化)。

关于ISO C++ Standard - Future Proposals邮件列表的讨论讨论了他们遗漏(删除)该功能的原因。 警告:长