【问题标题】:Why GCC rejects std::optional for references?为什么 GCC 拒绝 std::optional 引用?
【发布时间】:2017-03-15 22:28:02
【问题描述】:

std::optional<int&> xx; 只是不为最新的 gcc-7.0.0 快照编译。 C++17 标准是否包含 std::optional 以供参考?如果没有,为什么? (我猜在专用专业中使用指针的实现不会造成任何问题。)

【问题讨论】:

  • @Someprogrammerdude optional 不是这样工作的。否则,您也不能拥有optional<non_default_constructible>。您可以编写一个支持引用类型的可选类型。 Boost的可以。标准只是选择不这样做(由于operator=)。
  • 几乎整个参考点是,它们不是可选的
  • std::optional< std::reference_wrapper<int> > 怎么样:-D
  • @M.M 实际上在我的代码中,std::optoinal<std::variant<T&>>։) 更方便

标签: c++ gcc reference optional c++17


【解决方案1】:

因为optional,在 C++17 中标准化,不允许引用类型。这被设计排除在外。

这有两个原因。第一个是,从结构上讲,optional<T&> 等价于T*。它们可能有不同的接口,但它们做的事情是一样的。

第二件事是,标准委员会实际上没有就optional<T&> 应该如何表现的问题达成共识。

考虑以下几点:

optional<T&> ot = ...;
T t = ...;
ot = t;

最后一行应该做什么?它是否将ot 引用的对象复制分配给它,例如*ot == t?还是应该重新绑定存储的引用本身,例如ot.get() == &amp;t?更糟的是,作业前会do different things based on whether ot was engaged or not吗?

有些人会期望它做一件事,有些人会期望它做另一件事。所以无论你选择哪一方,都会有人感到困惑。

如果你改用T*,那会很清楚发生了什么:

T* pt = ...;
T t = ...;
pt = t;   //Compile error. Be more specific.
*pt = t;  //Assign to pointed-to object.
pt = &t;  //Change pointer.

【讨论】:

  • 好吧,我不会接受第一个原因,因为我需要一个通用代码中的统一接口。至于第二个原因,对我来说它绝对应该像*ot = t。顺便问一下boost::optional是这样的吗?
  • “所以无论你选择哪一方,都会有人感到困惑。” ——所以解决办法就是让双方都糊涂吧? ։)
  • 如果ot 没有参与,我什至会在ot = t 时抛出异常。
  • @Vahagn: "对我来说,它的行为绝对应该像*ot = t" 如果你这样做,你会如何重新绑定引用?将其设置为 NULL,然后将其设置为新的引用?后者将如何工作?如果您有optional&lt;optional&lt;T&amp;&gt;&gt; 怎么办? ot = nullopt 会脱离外包装还是内包装?
  • @NicolBolas 只需说o = t 它将重新绑定,*o = t 它将分配给引用。他们也有optional&lt;bool&gt; 的困惑,并决定直接对可选项进行操作将使用可选项,并且要对值进行操作,您必须取消引用。毕竟,如果你说optional&lt;int&gt; o=1; o = nullopt,那么它也会编译,尽管nullopt 不能转换为int
【解决方案2】:

在[可选]:

需要为引用类型或可能为 cv 限定类型 in_place_tnullopt_t 实例化可选模板的程序是不正确的。

没有std::optional&lt;T&amp;&gt;。现在,您必须使用std::optional&lt;std::reference_wrapper&lt;T&gt;&gt;

【讨论】:

  • 这会支持-&gt;吗? std::reference_wrapper 似乎没有实现 operator-&gt;。所以o-&gt;foo 不起作用。
  • @JohannesSchaub-litb 你需要两个间接寻址——比如o-&gt;get().foo,因为-&gt; 只是给你reference_wrapper。我确实希望最终我们得到optional&lt;T&amp;&gt;,它在分配时重新绑定,我已经让很多人相信这是正确的行为。
  • @JohannesSchaub-litb 我得出了同样的结论,所以我写了a wrapper class,最后到这里看看是否有人有类似的想法。这会将std::optional&lt;T&amp;&gt; 转换为std::optional&lt;std::reference_wrapper&lt;T&gt;&gt;,但它会自动解开operator-&gt;operator* 上的引用。 operator= 将重新绑定引用。
猜你喜欢
  • 2019-10-13
  • 2018-02-23
  • 1970-01-01
  • 2018-09-20
  • 2017-10-31
  • 2019-01-31
  • 1970-01-01
  • 2021-05-16
  • 2013-10-27
相关资源
最近更新 更多