Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ternary operator + C++11 constructor from initializer_list

While developing an application, I had the following problem. I wanted to return an empty std::list<string> when a given function pointer was null, or the result of that function otherwise. This is a simplified version of my code:

typedef std::list<std::string> (*ParamGenerator)();  std::list<std::string> foo() {     /* ... */     ParamGenerator generator = ...;     if(generator)         return generator();     else         return {}; } 

However, I usually like to use the ternary (?:) operator in these cases, so I tried using it this way (as usual):

return generator ? generator() : {}; 

But got this error:

somefile.cpp:143:46: error: expected primary-expression before ‘{’ token somefile.cpp:143:46: error: expected ‘;’ before ‘{’ token 

Does this mean I can't use the ternary operator to return objects created using their constructor from an initializer_list? Is there any particular reason for that?

like image 716
mfontanini Avatar asked Apr 02 '12 19:04

mfontanini


People also ask

What is ternary operator in C with example?

We use the ternary operator in C to run one code when the condition is true and another code when the condition is false. For example, (age >= 18) ? printf("Can Vote") : printf("Cannot Vote");

Can I call function in ternary operator?

Nope, you can only assign values when doing ternary operations, not execute functions.

How do you code a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

Can ternary operator be nested in C?

Nested Ternary operator: Ternary operator can be nested. A nested ternary operator can have many forms like : a ? b : c.


2 Answers

Standard writes in 8.5.4.1: List-initialization

Note: List-initialization can be used

  • as the initializer in a variable definition (8.5)
  • as the initializer in a new expression (5.3.4)
  • in a return statement (6.6.3)
  • as a function argument (5.2.2)
  • as a subscript (5.2.1)
  • as an argument to a constructor invocation (8.5, 5.2.3)
  • as an initializer for a non-static data member (9.2)
  • in a mem-initializer (12.6.2)
  • on the right-hand side of an assignment (5.17)

Nothing of them is a ternary operator. The more minimalistic return 1?{}:{}; is invalid too, what you want is impossible.

Of course you can explicitly call the constructor std::list<std::string>{}, but I would recommend to write out the if-else-block as you already did.

like image 196
ipc Avatar answered Oct 02 '22 15:10

ipc


When you do {} the compiler has no knowledge of the type you are expecting, so it's just a meaningless expression that the compiler doesn't know what to do with. Both sides of the : are evaluated separately, and only then will the compiler complain if the types don't match. I would just do this:

return generator ? generator() : std::list<std::string>(); 
like image 44
spencercw Avatar answered Oct 02 '22 14:10

spencercw