троичный оператор для обратного переключения - PullRequest
0 голосов
/ 25 сентября 2019

Согласно принятому ответу на предыдущее сообщение

Объявления не являются выражениями.Есть места, где выражения разрешены, но декларации нет.Один из них - левая часть?, Тринарный оператор.

Теперь рассмотрим следующий фрагмент кода:

#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(), которая является источником ошибки, должна быть закомментирована, истрока выше (в настоящее время закомментированная) должна была быть включена, код компилируется.

Обе строки используют троичный оператор для переключения возврата, хотя по-разному.И в обоих случаях левая часть ? внутри тернарного оператора не содержит никакого объявления (на самом деле это одно и то же выражение в обоих случаях).

Так почему один компилируется, а другойне

Ответы [ 2 ]

5 голосов
/ 25 сентября 2019

Это юридическое выражение:

{expression}?{expression}: {expression}

Это юридическое заявление:

возврат {expression};

Итак:

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

is:

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

Имеет форму:

return {expression};

Это совершенно законно.

С другой стороны, рассмотрим:

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

Это имеет вид:

{expression}?{statement}: {statement}

Это недопустимо, поскольку оператору ?: требуются выражения до и после двоеточия.

1 голос
/ 25 сентября 2019

Части троичного оператора должны быть выражениями.return не является выражением.Это утверждение.

...