在给定表达式返回对类型的引用时出错:`cond? * this:throw()`

时间:2017-03-27 19:05:51

标签: c++ visual-c++ g++ c++14 clang++

这似乎是一个错误,但我只是想确认一下。以下是否良好形成?如果没有,为什么不呢?

#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没有问题。

3 个答案:

答案 0 :(得分:10)

由于你有一个C ++ 14标签,代码是100%格式良好的C ++ 14。

Core issue 1560在这里删除了无偿的左值到右值转换,并且作为缺陷报告解析,它应该最终应用于提供这种模式的C ++ 98/03模式的编译器。

另见GCC bug 64372

答案 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>