为什么我们不能在未评估的上下文中使用大括号初始化程序?
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
中,我们有 2 个表达式,用逗号运算符分隔。如果无法评估第一个表达式,SFINAE 将启动并拒绝重载。如果可以计算表达式,那么,由于逗号运算符,void
正在从函数中 returned。
据我了解,void()
"constructs" 未评估上下文中的 void
对象(是的,这是合法的),然后由 decltype
所以 void
是函数的 return 类型。
我的问题是:为什么我们不能用void{}
来代替?它不是和"constructing"一个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)
这是一个表达式。 [expr.type.conv]/p2-3:
The expression T()
, where T
is a simple-type-specifier or
typename-specifier for a non-array complete object type or the
(possibly cv-qualified) void
type, creates a prvalue of the
specified type, whose value is that produced by value-initializing
(8.5) an object of type T
; no initialization is done for the
void()
case. [Note: ... - end note]
Similarly, a simple-type-specifier or typename-specifier followed by a
braced-init-list creates a temporary object of the specified type
direct-list-initialized (8.5.4) with the specified braced-init-list,
and its value is that temporary object as a prvalue.
您不能创建 void
类型的临时对象。 void()
是一个特殊的例外,允许您制作 void
纯右值。
我最近看到一些基于 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
中,我们有 2 个表达式,用逗号运算符分隔。如果无法评估第一个表达式,SFINAE 将启动并拒绝重载。如果可以计算表达式,那么,由于逗号运算符,void
正在从函数中 returned。
据我了解,void()
"constructs" 未评估上下文中的 void
对象(是的,这是合法的),然后由 decltype
所以 void
是函数的 return 类型。
我的问题是:为什么我们不能用void{}
来代替?它不是和"constructing"一个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)
这是一个表达式。 [expr.type.conv]/p2-3:
The expression
T()
, whereT
is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified)void
type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5) an object of typeT
; no initialization is done for thevoid()
case. [Note: ... - end note]Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.
您不能创建 void
类型的临时对象。 void()
是一个特殊的例外,允许您制作 void
纯右值。