为什么我们不能在未评估的上下文中使用大括号初始值设定项?

时间:2015-02-24 05:06:59

标签: c++ c++11 sfinae decltype

我最近看到一些基于SFINAE的代码如下所示:

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

基本上,上述功能使用SFINAE拒绝所有T类型的参数,这些参数不具有f()作为成员函数。 SFINAE发生在decltype,其中我们有两个由逗号运算符分隔的表达式。如果无法评估第一个表达式,SFINAE会启动并拒绝过载。如果可以计算表达式,那么,由于逗号运算符,函数将返回void

据我了解,void()&#34;构建&#34;未评估上下文中的void对象(是的,这是合法的),然后由decltype选择,因此void是函数的返回类型。

我的问题是:为什么我们不能使用void{}呢?它是否具有&#34;构建&#34;的相同效果?未评估的上下文中的void对象?我的编译器(g ++ / clang ++)不接受void{}代码

  

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

  

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

1 个答案:

答案 0 :(得分:8)

这是一个表达。 [expr.type.conv] / P2-3:

  

表达式T(),其中T简单类型说明符或    typename-specifier 表示非数组完整对象类型或   (可能是cv-qualified)void类型,创建一个prvalue   指定的类型,其值是由值初始化生成的   (8.5)T类型的对象;没有进行初始化   void()案例。 [注意:... - 结束注释]

     

同样,简单类型说明符 typename-specifier 后跟一个    braced-init-list 创建指定类型的临时对象   使用指定的 braced-init-list direct-list-initialized (8.5.4),   它的值是临时对象作为prvalue。

您无法创建void类型的临时对象。 void()是一个特殊例外,可让您制作void prvalue。