std ::引用类型的可选专门化

时间:2014-11-11 05:18:08

标签: c++ c++11 stl optional boost-optional

为什么std::optional(目前 libc ++ 中的std::experimental::optional)没有针对参考类型的专业化(与boost::optional相比)?

我认为这将是非常有用的选择。

STL 中是否存在引用可能已存在的对象语义的对象?

5 个答案:

答案 0 :(得分:15)

当讨论n3406(提案的第2版)时,一些委员会成员对可选参考文献感到不舒服。在n3527(修订版#3)中,作者决定将可选引用作为辅助提议,以增加获得可选值的可能性并将其置于C ++ 14中。虽然由于各种其他原因,可选项并未完全进入C ++ 14,但委员会并未拒绝可选引用,如果有人提出,可以在将来自由添加可选引用。

答案 1 :(得分:6)

确实存在引用可能现有对象语义的内容。它被称为(const)指针。一个普通的旧非拥有指针。引用和指针之间有三个不同之处:

  1. 指针可以为null,引用不能。这正是您希望通过std::optional避免的差异。
  2. 指针可以重定向到指向别的东西。使它成为常数,这种差异也会消失。
  3. 参考不需要->*取消引用。这是纯粹的语法糖,可能因为1.并且指针语法(解除引用和转换为bool)正是std::optional为访问值并测试其存在所提供的。
  4. <强>更新 optional是值的容器。与其他容器(例如vector)一样,设计不包含引用。如果你想要一个可选的引用,使用一个指针,或者如果你确实需要一个与std::optional具有类似语法的接口,那么为指针创建一个小的(和普通的)包装器。

    更新2:至于问题为什么没有这样的专业化:因为委员会只是选择了它。 的基本原理可能可以在论文的某处找到。这可能是因为他们认为指针足够了。

答案 2 :(得分:4)

std::optional <T&>的主要问题是-在以下情况下optRef = obj应该做什么:

optional<T&> optRef;
…;
T obj {…};
optRef = obj; // <-- here!

变量:

  1. 始终重新绑定-(&optRef)->~optional(); new (&optRef) optional<T&>(obj)
  2. 通过— *optRef = obj(在!optRef之前为UB)进行分配。
  3. 如果为空则绑定,否则进行赋值-if (optRef) {do1;} else {do2;}
  4. 没有赋值运算符-编译时错误“试图使用已删除的运算符”。

每个变体的优点:

  1. 始终重新绑定(由boost::optionaln1878选择):

    • 始终满足!optRefoptRef.has_value() —后置条件&*optRef == &obj的情况之间的一致性。
    • 在以下方面与通常的optional<T>保持一致:对于通常的optional<T>,如果将T::operator=定义为破坏和构造(并且有人认为它必须是 只是破坏和构造的优化),opt = …实际上 的行为类似于(&opt)->~optional(); new (&opt) optional<T&>(obj)
  2. 分配方式:

    • 在以下方面,与纯T&的一致性:对于纯T&ref = …分配通过(不重新绑定ref)。
    • 在以下方面与通常的optional<T>保持一致:对于通常的optional<T>,当opt.has_value()时,opt = …被要求分配通过,而不是破坏和构造(参见n3672on cppreference.com中的template <class U> optional<T>& optional<T>::operator=(U&& v)
    • 在以下方面与通常的optional<T>保持一致:两者都至少以某种方式定义了operator=
  3. 如果为空则绑定,否则进行赋值-我看不出任何真正的好处,恕我直言,只有当#1的支持者与#2的支持者争论时,该变体才会出现,但是从形式上讲,它与{ {1}}(恕我直言,恕我直言)。

  4. 没有赋值运算符(由n3406选择):

    • 在以下方面与纯template <class U> optional<T>& optional<T>::operator=(U&& v)保持一致:纯T&不允许重新绑定自身。
    • 没有模棱两可的行为。

另请参阅:

答案 3 :(得分:0)

如果我冒险猜测,那将是因为std :: experimental :: optional规范中的这句话。 (第5.2节,第1节)

  

需要实例化模板optional的程序   对于引用类型,或者可能是cv限定类型in_place_t或   nullopt_t格式不正确。

答案 4 :(得分:0)

恕我直言,可以使用std::optional<T&>。但是,模板存在一个微妙的问题。如果有引用,模板参数可能会变得难以处理。

就像我们解决模板参数中的引用问题一样,我们可以使用std::reference_wrapper来避免缺少std::optional<T&>。因此现在它变成std::optional<std::reference_wrapper<T>>。但是,我建议您反对这种用法,因为1)写签名(返回返回类型为我们节省了一点时间)和签名的使用(我们必须调用std::reference_wrapper<T>::get()以获得真正的参考)太冗长了,和2)大多数程序员已经被指针折磨了,这就像本能的反应,当他们收到一个指针时,他们首先会测试它是否为空,所以现在不再是一个大问题了。