Why cannot we use brace initializer in an un-evaluated context?
c++, c++11, decltype, sfinae
Solution
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.
Problem
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)