What is calling void(); doing?
Assuming var->member()
has type void
,
var ? var->member() : void();
has type void
and either evaluates var->member()
or evaluates void()
if var
is null.
Now, void()
is an expression; according to [expr.type.conv]/2
, it just does nothing:
if the type is cv
void
and the initializer is()
or{}
(after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization.
void
is a type, but if it's followed by ()
it does initialization of a prvalue
of type void
.
The reason for doing such a thing, is that the return type of var->member()
is void
, and the second and third operands of ?:
operator must be the same. Note: They don't have to be exactly the same; there are conversion rules that say when the the types can be different.
You have shown one way to get a void
prvalue for one of the operands, but there are a number of ways to achieve the same effect,
var ? var->member() : throw 42;
a throw
expression has the void
type, so this compiles. It won't do nothing
if var
is nullptr
of course, since it throws.
This statement will compile and do nothing,
var ? var->member() : []{}();
where the second operand is an anonymous function returning void
.
and this one,
var ? var->member() : decltype(var->member())();
which in my opinion says most clearly, "I'm trying to get the same type in both operands".
That being said, I don't see why one would ever write this code. If there's no meaningful else branch, then there is already the if
construct in the language, and the conditional ?:
operator is the wrong tool for the job.
Edit: @walnut's (now deleted) answer actually shows a use-case: in c++11, but pre-c++14, the ?:
operator is the only way to express conditional branches in constexpr functions.
You are just "constructing" a prvalue (not a variable, for the reason suggested in the comments) of type void
, just as int()
would default-construct an int
.
As others said in the comments, the second alternative is pejorative. The ternary operator is, well, ternary because it has the if
, the then
, and the else
parts. If you don't need an else
, why would you write one and leave it empty?
That alternative is even uglier and more cryptic than this,
if(var){
var->member();
} else {}
which may just look stupid.