为什么我们不能在未求值的上下文中使用大括号初始值设定项
Why cannot we use brace initializer in an un-evaluated context?
我最近看到了一些基于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。
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- 为什么我们不能直接使用类模板来推导方法模板?荸荠属
- 为什么我们不能在C++中初始化类的成员变量
- 为什么我们不能将使用异或运算找到的整数转换为字符?
- 为什么我们甚至需要删除运算符?(我们不能只使用删除[]吗)
- 如果普通默认构造函数不执行任何操作,为什么我们不能使用 malloc 创建平凡可构造的对象?
- 链表指针赋值为什么我们不能直接将尾巴分配给 temp 而不是尾巴>尾巴下一个
- 我们不能在 c++ 中只有对象的变量吗?
- 为什么在 2019 年我们仍然不能使用 ctypes 从 Python 调用C++?
- 为什么我们不能使用整数到字符串直接转换,但可以按位到字符串?
- 为什么我们不能用抽象类创建容器?
- 为什么我们需要在 Visitor 模式中 accept(),为什么我们不能直接调用 visitor.visit()?
- 为什么我们不能同时实现两个方法'getAB() &&'和'getAB()'?
- 为什么我们不能像在java中使用的那样使用新的ClassName(),而不是使用新的ClassName?
- 为什么我们不能在C++中进行三方比较?
- 我们不能在不使用指向对象的指针的情况下创建节点C++吗?
- 为什么我们不能在声明之前使用预处理器 #define 常量
- 为什么我们不能在模板专业化的开始/中间使用可变参数模板(以及如何模拟)?
- 为什么我们不能在C++中覆盖函数指针?
- 为什么我们不能泛化指针声明?