Basically, I'd like to know why the compiler rejects ptr2
declaration:
int main() {
// this one works
decltype(void())* ptr1;
// this one does not
decltype(void{})* ptr2;
}
Take a look at this code if you think that ptr1
is a function pointer:
#include <iostream>
using namespace std;
template <class T>
void f(T t) {
cout << __PRETTY_FUNCTION__ << endl;
}
int main() {
decltype(void())* ptr;
f(ptr);
}
The output is void f(T) [with T = void*]
.
It seems like () and Void both mean exactly the same thing (the type Void) when used in the context of a type declaration, but in all other contexts, () instead means an instance of the type Void, ie the same as Void().
void * - pointer to void (this can point to any object, not to a function) void * () - function taking no arguments and returning void *
The void main() indicates that the main() function will not return any value, but the int main() indicates that the main() can return integer type data. When our program is simple, and it is not going to terminate before reaching the last line of the code, or the code is error free, then we can use the void main().
public is an access specifier. void is a return type, or more specifically the lack of a return type.
Void main () is the entry point for execution in C program. The void is a keyword that represents function will not return anything but a void value. Main is the name of the function and () represents parameter list that can be passed to function in this case nothing is passed.
1 : containing nothing : empty void space. 2 : being without something specified : devoid a person void of common sense. 3 : of no legal force or effect a void contract.
[expr.type.conv]
2 The expression
T()
, whereT
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 typeT
; no initialization is done for thevoid()
case. [...]
N.B. void
is a simple-type-specifier.
3 Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.
Thanks to Keith Thompson for pointing out that a temporary object is created in /3, whereas a value is created in /2.
When we take a look at [basic.types]/5
Incompletely-defined object types and the
void
types are incomplete types (3.9.1). Objects shall not be defined to have an incomplete type.
It now becomes clear that void{}
is not allowed as it would create a (temporary) object. void()
however "only" creates a (pr)value. I don't think there's a difference in the implementation (behaviour) for those two cases, but different language rules apply to them. One of those rules forbids creation of an object of type void
, hence the error.
Ad decltype(void())
: decltype(e)
takes an expression e
. In [dcl.type.simple]/4, the applicable definition of decltype(e)
is:
otherwise,
decltype(e)
is the type ofe
(as void()
yields a prvalue and is not an id-expression).
Therefore, decltype(void())
yields void
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With