【问题标题】:Why operator ?: lost lvalue-ness if second or third argument is throwing expression?为什么运算符?:如果第二个或第三个参数是抛出表达式,则会丢失左值?
【发布时间】:2014-07-30 18:56:36
【问题描述】:

在 C++ 中,运算符 ?: 如果第二个和第三个参数是相同类型的左值,则可以是一个左值,例如:

int foo = 0, bar = 1;
bool condition = true;
(condition ? foo : bar) = 42; // correct

也可以在这个操作符中抛出一些东西:

bar = (condition ? foo : throw 42); // still correct

但是这段代码无法编译,因为左表达式不是左值:

(condition ? foo : throw 42) = bar; // compile error

我在 C++ 标准中检查了这一事实并阅读了以下内容:

第二个或第三个操作数(但不是两者)是 throw 表达式 (15.1);结果是另一个的类型,是一个右值

这个规则有什么解释?

【问题讨论】:

  • condition ? foo : bar = 42; condition ? foo : (bar = 42);
  • 谢谢,我加了大括号。我的问题仍然存在。
  • @dyp 是的,看起来这在 C++14 中已修复。
  • 如果条件为真,则结果为foo = bar。但是如果为false,会导致throw 42 = bar

标签: c++


【解决方案1】:

这是CWG defect 1560。引用缺陷报告:

作为 条件表达式 的一个操作数出现的左值 另一个操作数是 throw-expression 的操作数被转换为 prvalue,无论如何使用条件表达式:[...] 这似乎是无缘无故和令人惊讶的。

CWG 1550 的分辨率已解决此问题,现在 [expr.cond]/2.1 表示:

[If] 第二个或第三个操作数(但不是两者)是 a(可能 带括号的)抛出表达式;结果是 其他的类型和值类别。

所以它应该适用于最近的编译器。

【讨论】:

  • 作为一名程序员,我要求任何人都不要使用它。我喜欢这是一个编译错误。 ;-)
  • @MobyDisk 在成员初始化列表中很有用,例如: struct SomeStruct { SomeStruct(int x) : m_x(x > 0 ? x : throw "error") {} int m_x; };
  • @maxim.yurchuk 但这种情况目前有效,唯一的问题是初始化引用。
【解决方案2】:

throw 的优先级低于?:=。你实际上在说的是

condition ? foo : throw (42 = bar);

显然42 不能分配为右值。

来源:http://en.cppreference.com/w/cpp/language/operator_precedence

(答案是指原始问题的语法...)

【讨论】:

  • 抱歉,我忘记带牙套了。现在我解决了问题并添加了它们。
  • 我认为OP问的很明显,他在语法上犯了错误,可以在评论中提到,但不是在回答中
猜你喜欢
  • 2020-01-19
  • 2013-09-11
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
  • 1970-01-01
  • 2015-12-27
  • 2012-02-28
  • 1970-01-01
相关资源
最近更新 更多