I was given a piece of code that uses void()
as an argument. The code doesn't compile... obviously?
Can we instantiate anything of type void
? I believed the answer was no, with the exception of a void*
. For example:
- Writing the function
void askVoid(void param) {}
errors:
A parameter may not have void
type
- Writing the function
void askNaught() {}
and calling it with askNaught(void())` errors:
error C2660: takeNaught
: function does not take 1 arguments
- Writing the templatized function
template <typename T> void takeGeneric(T param) {}
and calling it with takeGeneric(void())
errors:
error C2893: Failed to specialize function template void takeGeneric(T)
- Declaring
void voidType
errors:
Incomplete type is not allowed
- Declaring
auto autoVoid = void()
errors:
Cannot deduce auto
type
- Declaring
void* voidPtr
works fine, but remove_pointer_t<decltype(voidPtr)> decltypeVoid
errors:
error C2182: decltypeVoid
: illegal use of type void
That's it, right? There is no place for void()
in C++ is there? This is just bad code I've been given, right?
The expression void()
is a prvalue of type void
and can be used anywhere such an expression may be used, which [basic.fundamental]/9 helpfully provides a list:
- As an expression-statement:
void();
- As the second or third operand of a conditional operator:
true ? throw 1 : void()
- As an operand of the comma operator:
++it1, void(), ++it2
- As the operand of
decltype
or noexcept
: using my_void = decltype(void()); static_assert(noexcept(void()), "WAT");
- In a
return
statement of a function returning (possibly cv-qualified) void
: const void f() { return void(); }
- As an operand of an explicit conversion to (possibly cv-qualified)
void
: static_cast<const void>(void())
An expression of type void
can also be used as the operand of typeid
, but void()
in particular would be parsed as a type, not an expression, in this context.
C++ (and I say C++, not C) allows (§6.6.3 comma 2) functions with void
return type to return a void
expression, that is:
void foo() { return void(); }
But notice it is not constructing a temporary void
!
You can take a void()
as function parameter:
void test(void()) { ... }
Which expands to:
void test(void (*)())
Which is a function pointer to a method which returns void and takes no arguments.
Full example:
void abc() {}
void test(void()) { }
int main() {
test(abc);
}
You can use void()
as a callable type, as an example std::function<void()> f;
is a valid statement.
Moreover, as from 8.3.5/4:
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
That means that this is valid:
template<typename T>
struct F;
template<typename R, typename... A>
struct F<R(A...)> { };
int main () {
F<void(void)> s;
}
Here you are not instantiating anything of type void
, but you are using it (let me say) as a parameter list of a callable type.
Not sure if this replies to your question, I've not clear what the question actually is.
There is no place for void() in C++ is there?
As an expression, void()
is valid in C++.
From the standard, $5.2.3/2 Explicit type conversion (functional notation) [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.
From cppreference.com:
new_type ( )
If new_type
is an object type, the object is value-initialized;
otherwise, no initialization is done. If new_type
is (possibly
cv-qualified) void
, the expression is a void
prvalue.