这似乎是一个错误,但我只是想确认一下。以下是否良好形成?如果没有,为什么不呢?
#include <iostream>
struct X
{
int value;
constexpr X(int value) : value(value) {}
constexpr X& do_something(int x)
{
return x < 3 ? *this : throw("FAIL");
//return *this;
}
};
int main()
{
X x(2);
std::cout << x.do_something(1).value << std::endl;
}
在VC++2015 R3
下使用默认解决方案切换,我得到:
warning C4172: returning address of local variable or temporary
带有开关g++ (GCC) 5.4.0
的 -Wall -pedantic
我得到了:
error: invalid initialization of non-const reference of type ‘X&’ from an rvalue of type ‘X’
return x < 3 ? *this : throw("FAIL");
^
但是,使用开关clang version 3.9.1 (tags/RELEASE_391/final)
的{{1}}没有问题。
当然使用-Wall -pedantic
没有问题。
答案 0 :(得分:10)
由于你有一个C ++ 14标签,代码是100%格式良好的C ++ 14。
Core issue 1560在这里删除了无偿的左值到右值转换,并且作为缺陷报告解析,它应该最终应用于提供这种模式的C ++ 98/03模式的编译器。
答案 1 :(得分:3)
C ++ 11 15/2说:
A try-block is a statement (Clause 6). A throw-expression is of type void...
然后 5.16 / 2 :(来自@Fred Larson Mjollnir&#39; d然后未被欺骗的问题)
如果第二个或第三个操作数的类型为void,则为 lvalue-to-rvalue(4.1),array-to-pointer(4.2)和 函数到指针(4.3)标准转换是在 第二和第三个操作数,以下之一应保持:
- 第二个或第三个操作数(但不是两个)是一个throw-expression (15.1);结果是另一个的类型,是一个prvalue。
- 第二个和第三个操作数都有类型 无效;结果是void类型,是一个prvalue。
所以从这里我们看到条件表达式运算符(三元)部分是合法的。 但是 ?:
的结果是一个prvalue,然后它不能合法地绑定到非const X&
返回类型,实际上是不正确的。
答案 2 :(得分:2)
为什么不使用既能确保工作又更容易阅读的东西呢?例如:
X& do_something(int x)
{
if (x >= 3)
throw("FAIL");
return *this;
}
我不是关于编译器的专家,但我的猜测是,如果编译器处理特定的极端情况,您发布的示例将起作用。我读这篇文章的方式,你的do_something(int x)
函数扩展到了这个:
X& do_something(int x)
{
if x < 3
return *this;
else
return throw("FAIL");
}
现在,throw
是一个关键字,因此没有返回值,所以严格来说这是一个编译时错误。但是,我猜编译器(或者至少其中一些编译器)非常友好:&#34;哦,好吧......这里没有返回值,但是throw
是一个无论如何,这种特殊情况会导致函数无法返回,所以请不要抱怨并让运行时的异常处理解决这个问题。&#34;
我个人不想利用编译器的机会,尽量让事情尽可能地保持一致,但......虽然这可能是一种更好的做法,但也可能只是个人偏好。 / p>