return 开关的三元运算符

ternary operator for return switch

根据

的已接受答案

Declarations are not expressions. There are places where expressions are allowed, but declararions are not. The left hand side of ?, the trinary operator, is one of them.

现在,考虑以下代码段:

#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));
}

函数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

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

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

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

这是一个合法的表达式:

{expression} ? {expression} : {expression}

这是一个法律声明:

return {expression};

所以:

return (invocation_count % 2) ? (status::invalid) : (status::valid);

是:

return {expression} ? {expression} : {expression};

其形式为:

return {expression};

这是完全合法的。

另一方面考虑:

(invocation_count % 2) ? (return (status::invalid)) : (return (status::valid));

其形式为:

{expression} ? {statement} : {statement}

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

部分三元运算符必须是表达式。 return 不是表达式。这是一个声明。