C++ 为什么我们不能在未计算的上下文中使用大括号初始值设定项?
我最近看到一些基于SFINAE的代码如下所示:C++ 为什么我们不能在未计算的上下文中使用大括号初始值设定项?,c++,c++11,sfinae,decltype,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) } 模板 自动测试(T&myclass)->decltype(myclass.f(),void()) { //在此处执行操作,不返回任何内容(无效) }
template <typename T>
auto test(T &myclass) -> decltype(myclass.f(), void())
{
// do something here, don't return anything (void)
}
模板
自动测试(T&myclass)->decltype(myclass.f(),void())
{
//在此处执行操作,不返回任何内容(无效)
}
基本上,上面的函数使用SFINAE拒绝所有类型为T
的参数,这些参数没有f()
作为成员函数。SFINAE发生在decltype
中,其中有两个表达式,由逗号运算符分隔。如果无法计算第一个表达式,SFINAE将启动并拒绝重载。如果可以对表达式求值,则由于使用逗号运算符,函数将返回void
据我所知,void()
“在未计算的上下文中构造”一个void
对象(是的,这是合法的),然后由decltype
选择该对象,因此void
是函数的返回类型
我的问题是:为什么我们不能使用void{}
来代替呢?在未评估的上下文中,它不具有“构造”一个void
对象的效果吗?我的编译器(g++/clang++)不接受void{}
代码
错误:非对象类型“void”的复合文本
(g++4.9/g++5)
及
错误:非法初始值设定项类型“void”
(clang++3.5)
这是一个表达。[expr.type.conv]/p2-3: 表达式
T()
,其中T
是一个简单的类型说明符或
非数组完整对象类型或
(可能是cv限定)void
type,创建
指定的类型,其值是由值初始化生成的值
(8.5)类型为T
的对象;未对该文件进行初始化
void()
case。[注:…-结束注]
类似地,简单类型说明符或类型名说明符后跟
带括号的init list创建指定类型的临时对象
使用指定的带括号的初始列表初始化直接列表(8.5.4),
它的值是作为prvalue的临时对象
无法创建类型为
void
的临时对象void()
是一个特殊的异常,允许您创建void
prvalue。它是函数声明吗?我原以为不能在decltype
中使用函数声明,而只能使用函数名,但我可能又被最烦人的解析咬了一口;)3分钟后:实际上我很确定它不是MVP,因为decltype(int(int))x代码>被拒绝,但decltype(int())x
有效,并且x
的类型为int
。有趣的。。。所以T()
是一个prvalue,而T{}
是(几乎)一个xvalue,如果我理解的话correctly@vsoftco“其值是作为prvalue的临时对象”。