Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot we use brace initializer in an un-evaluated context?

I have recently seen some SFINAE-based code that looks like this:

template <typename T>
auto test(T &myclass) -> decltype(myclass.f(), void()) 
{
    // do something here, don't return anything (void)
}

Basically the function above uses SFINAE to reject all parameters of type T that don't have f() as a member function. The SFINAE takes place in the decltype, where we have 2 expressions separated by the comma operator. If the first expression cannot be evaluated, SFINAE kicks in and rejects the overload. If the expression can be evaluated, then, because of the comma operator, void is being returned from the function.

As far as I understand, void() "constructs" a void object in an un-evaluated context (yes, this is legal), which is then picked by the decltype so void is the return type of the function.

My question is: why cannot we use void{} instead? Doesn't it have the same effect of "constructing" a void object in an un-evaluated context? My compiler(s) (g++/clang++) don't accept the void{} code

error: compound literal of non-object type 'void' (g++4.9/g++5)

and

error: illegal initializer type 'void' (clang++ 3.5)

like image 874
vsoftco Avatar asked Feb 24 '15 05:02

vsoftco


1 Answers

It's an expression. [expr.type.conv]/p2-3:

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: ... - end note]

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.

You can't create a temporary object of type void. void() is a special exception that allows you to make a void prvalue.

like image 181
T.C. Avatar answered Nov 15 '22 13:11

T.C.