lundi 23 février 2015

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)



Aucun commentaire:

Enregistrer un commentaire