返回开关的三元运算符

Vin*_*nod 1 c++ return ternary-operator

根据上一个帖子的公认答案

声明不是表达式。在某些地方允许使用表达式,但不允许使用声明。三元运算符?的左侧是其中之一。

现在,考虑以下代码段:

#include <iostream>
using std::cout;
using std::endl;

enum struct status{invalid=0, valid};

status test (void);

int main (void){
    status s = test();
    cout << static_cast<int>(s) << endl;
    return (0);
}

status test (void){
    static auto invocation_count = 0;
    ++invocation_count;
    //return (invocation_count % 2) ? (status::invalid) : (status::valid);
    (invocation_count % 2) ? (return (status::invalid)) : (return (status::valid));
}
Run Code Online (Sandbox Code Playgroud)

该函数test()无法编译(请注意,编译器错误日志在原始测试代码中显示行号):

g++ -ggdb -std=c++17 -Wall -Werror=pedantic -Wextra  -c code.cpp
code.cpp: In function ‘status test()’:
code.cpp:19:31: error: expected primary-expression before ‘return’
     (invocation_count % 2) ? (return (status::invalid)) : (return (status::valid));
                               ^~~~~~
code.cpp:19:31: error: expected ‘)’ before ‘return’
code.cpp:19:83: error: expected ‘:’ before ‘;’ token
     (invocation_count % 2) ? (return (status::invalid)) : (return (status::valid));
                                                                                   ^
code.cpp:19:83: error: expected primary-expression before ‘;’ token
code.cpp:20:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^
make: *** [makefile:20: code.o] Error 1
Run Code Online (Sandbox Code Playgroud)

但是,如果test()要注释掉其中的最后一行(这是错误的来源),并且要启用上面的行(当前已注释掉),则代码将编译。

两条线都使用三元运算符进行返回切换,尽管有所不同。而且在这两种情况下,?三元运算符内部的左侧都不包含任何声明(实际上,在两种情况下它都是相同的表达式)。

那么,为什么一个编译而另一个则不编译呢?

Dav*_*rtz 5

这是一个法律表达:

{expression}{expression}{expression}

这是法律声明:

回报{expression};

所以:

返回(invocation_count%2)?(状态::无效):(状态::有效);

是:

回报{expression}{expression}{expression};

形式如下:

回报{expression};

那是完全合法的。

另一方面,请考虑:

(invocation_count%2)?(返回(状态::无效)):(返回(状态::有效));

其形式为:

{expression}{statement}{statement}

这是不合法的,因为?:运算符在冒号之前和之后都需要表达式。