如果我们有
std::experimental::optional<int> x;
以下两行都没有编译:
std::experimental::optional<unsigned int> y; y = x;
std::experimental::optional<unsigned int> z(x);
...即使在我看来有意义,就像将int
分配给unsigned int
一样。为什么不能这样做?也就是说,库没有为这种情况实现复制ctor和赋值运算符而避免的陷阱是什么?
答案 0 :(得分:4)
你不能这样做,因为std::experimental::optional
对于构造函数和赋值运算符没有适当的重载。
肯定可以提供这样的界面。事实上,提出的接口所基于的boost optional确实有一个重载的构造函数和赋值运算符,用于从另一个optional
实例构造。
proposal有一节“与Boost.Optional比较”,其中包含一个包含讨论过载的比较表。除了一般性陈述之外,该提案没有给出差异的理由:
目前的提案反映了我们在界面的明确性,通用性和灵活性之间任意选择平衡。
具有参考实现的git repo和ISO 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
。问题是,如果
T
和U
同时构建optional<U>
,我们就会有歧义,现在我们可以 选择3中的一个:
- 编译错误,让程序员决定
- 首选取消装箱构造函数
- 首选转发构造函数
醇>
我真的认为这根本不是什么问题,但我不会在这里开始讨论。
答案 2 :(得分:2)
将n3672提案与Boost.Optional进行比较。其中一个主要差异是std::optional
不允许从optional<U>
转换为optional<T>
。 std::optional
在Boost.Optional
之后({1}}重复建模{至少1.48.0,不知道自那以后发生了什么变化)。
关于ISO C++ Standard - Future Proposals邮件列表的讨论讨论了他们遗漏(删除)该功能的原因。 警告:长