1

According to the accepted answer to a previous post

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.

Now, consider the following code segment:

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

The function test() does not compile (note the compiler error log displays line numbers in the original test code):

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

However, if the last line inside test(), which is the source of error, were to be commented out and the line above (presently commented out) were to be enabled, the code compiles.

Both the lines use the ternary operator for return switch, albeit differently. And in both cases, the left hand side of the ? inside the ternary operator does not include any declaration (in fact it is the same expression in both cases).

So why does one compile while the other doesn't?

Vinod
  • 925
  • 8
  • 9

2 Answers2

5

This is a legal expression:

{expression} ? {expression} : {expression}

This is a legal statement:

return {expression};

So:

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

is:

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

Which has the form:

return {expression};

That's perfectly legal.

On the other hand consider:

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

This has the form:

{expression} ? {statement} : {statement}

That is not legal because the ?: operator requires expressions before and after the colon.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

Parts of ternary operator must be expressions. return is not an expression. It is a statement.

Eugene
  • 6,194
  • 1
  • 20
  • 31