在给定表达式的情况下返回对类型的引用时出错:“cond ?*这个 : 投掷()'

Error when returning reference to type given the expression: `cond ? *this : throw()`

本文关键字:这个 cond 投掷 出错 情况下 表达式 返回 引用 类型      更新时间:2023-10-16

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

#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)使用交换机-Wall -pedantic没有问题。

使用return *this;当然没有问题。

由于您有一个 C++14 标签,因此代码是 100% 格式正确的 C++14。

核心问题 1560 删除了此处的无偿左值到右值转换,作为缺陷报告解决方案,它最终应该一直应用回提供这种模式的编译器的 C++98/03 模式。

另请参阅 GCC 错误 64372。

C++11 15/2 说:

A try-block is a statement (Clause 6). A throw-expression is of type void...

然后5.16/2:(来自拉尔森·姆约尔尼尔@Fred然后未被欺骗的问题(

如果第二个或第三个操作数的类型为 void,则 左值到右值 (4.1(、数组到指针 (4.2( 和 函数到指针 (4.3( 标准转换在 第二和第三操作数,以及下列操作数之一应成立:

— 该 第二个或第三个操作数(但不是两个(是抛出表达式 (15.1);结果属于另一个的类型,并且是 prvalue。

— 第二个和第三个操作数都有类型 无效;结果的类型为 void,并且是 PR值。

因此,从这里我们看到条件表达式运算符(三元(部分是合法的。但是?:的结果是一个 prvalue,因此不能在法律上约束于非常量X&返回类型,并且实际上是格式错误的。

为什么不使用既能正常工作又更容易阅读的东西呢?例如:

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是一个关键字,因此没有返回值,因此严格来说这是一个编译时错误。但是,我想编译器(或至少其中一些(会很好心地说:">哦,好吧......这里没有返回值,但throw特殊情况会导致函数无论如何都不会返回,所以我们不要抱怨,让运行时的异常处理来处理这个问题。

我个人不喜欢冒险使用编译器并尝试让事情尽可能简单,但是......虽然这可以说是一种更好的做法,但它也可能只是个人偏好。