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

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

本文关键字:不能 我们 为什么 上下文      更新时间:2023-10-16

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

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

基本上,上面的函数使用SFINAE来拒绝所有没有f()作为成员函数的T类型的参数。SFINAE发生在decltype中,其中有两个由逗号运算符分隔的表达式。如果无法计算第一个表达式,则SFINAE将启动并拒绝重载。如果表达式可以求值,那么由于逗号运算符,函数将返回void

据我所知,void()在未求值的上下文中"构造"了一个void对象(是的,这是合法的),然后由decltype拾取,因此void是函数的返回类型。

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

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

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

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

表达式T(),其中T简单类型说明符非数组完整对象类型的typename说明符或(可能是cv限定的)void类型,创建指定的类型,其值是由值初始化产生的值(8.5)CCD_ 17类型的对象;没有对进行初始化CCD_ 18病例。注释:…-结束注释]

类似地,简单类型说明符类型名说明符raked init list创建指定类型的临时对象直接列表用指定的支持的初始化列表初始化(8.5.4),并且它的值是作为prvalue的那个临时对象。

不能创建void类型的临时对象。void()是一个特殊的例外,允许您生成void prvalue。

相关文章: