geza
geza

Reputation: 29942

What is the purpose of a void() expression?

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

Answers (2)

AnT stands with Russia
AnT stands with Russia

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

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

Related Questions