Reputation: 29942
You cannot declare a void
variable:
void fn() {
void a; // ill-formed
}
Yet this compiles:
void fn() {
void(); // a void object?
}
What does void()
mean? How is it useful? Why is void a;
ill-formed, while void()
OK?
void fn() {
void a = void(); // ill-formed
}
Upvotes: 2
Views: 364
Reputation: 320391
Syntactically void()
is an explict type conversion written in functional notation (see 5.2.3).
Note that even in "classic" C (C89/90) explicit conversions to void
were already allowed. Of course, in C one has to use "classic" C-style cast notation and supply an argument. Any expression can be cast to void
in C, including expressions that are already void
. This functionality migrated unchanged to cast notation of explicit type conversion in C++ (it is handled by static_cast
branch of its functionality, i.e. you can static_cast
to void
in C++).
Taking the above into account, it is not surprising that conversion to void
is also consistently supported by the alternative C++ cast syntax - functional notation. And once you understand that, it is no surprise that it was extended to support the "argument-less" version - void()
.
The usefulness of this in C++ will include such contexts as generic functions
template <typename T>
T foo() {
...;
return T(); // remains valid even when `T == void`
}
Note that in C++ it is perfectly legal to return void
pseudo-values from void
functions. The ability to create such void()
pseudo-values eliminates the need to write dedicated void
specializations for functions like the one above.
As a side note, void()
stands for explicit type conversion only if the context forces it to be interpreted as an expression, as in your example. When context calls for a type name (e.g. int foo(void())
or using T = void();
) it actually declares a nameless function that returns void
and takes no arguments.
Upvotes: 3
Reputation: 28987
The statement
void();
creates a void value and then discards it. (You can't actually do much with a void value other than discard it or return it.)
The standard† says in 5.2.3 [expr.type.conv
The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of type T; no initialization is done for the void() case
Note that it explictaly calls out that void()
is legal.
† My link is to N4296 which was the last public committee draft before C++14, however the various versions of the standard do not vary here.
Edit
Is it useful? Explicitly like this? No. I can't see a use for it. It is however, useful in template functions which sometimes do something like:
template <typename T>
T foo() {
if (prepare_for_for()) {
return do_foo();
} else {
return T();
}
}
And this will work, even for T
== void
.
Upvotes: 6