什么叫 void();正在做?
What is calling void(); doing?
我发现 void();
在三元运算符的 'else' 分支中被用作 'do-nothing',作为空指针检查的 shorthand
if(var){
var->member();
}
作为
var ? var->member() : void();
但我似乎找不到以这种方式使用的 void
关键字的任何引用,这是对 void
关键字本身的函数或函子调用吗?或者它什么都不投射到 void
的类型?或者这只是 pass
?
之类的 C++ 语法
编辑:
在这种情况下,member()
的 return 类型是 void
。
你只是在“构造”一个 void
类型的纯右值(不是变量,因为评论中建议的原因),就像 int()
默认构造一个 int
.
正如其他人在评论中所说,第二种选择是贬义的。三元运算符是 ternary,因为它具有 if
、then
和 else
部分。如果您不需要 else
,为什么要写一个并将其留空?
这个选择比这个更丑陋、更神秘:
if(var){
var->member();
} else {}
这可能看起来很愚蠢。
假设 var->member()
的类型为 void
,
var ? var->member() : void();
具有类型 void
,如果 var
为空,则计算 var->member()
或计算 void()
。
现在,void()
是一个表达式;根据 [expr.type.conv]/2
,它什么都不做:
if the type is cv void
and the initializer is ()
or {}
(after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization.
void
是一种类型,但如果它后面跟着 ()
,它会初始化 void
.
类型的 prvalue
原因,var->member()
的return类型是void
,第二个和第三个?:
运算符的操作数必须相同。注意:它们不必完全相同; conversion rules 表示类型何时可以不同。
您已经展示了一种为其中一个操作数获取 void
纯右值的方法,但是还有多种方法可以达到相同的效果,
var ? var->member() : throw 42;
a throw
表达式具有 void
类型,因此可以编译。当然,如果 var
是 nullptr
,它不会执行 nothing
,因为它会抛出。
此语句将编译但不执行任何操作,
var ? var->member() : []{}();
其中第二个操作数是匿名函数 returning void
.
还有这个,
var ? var->member() : decltype(var->member())();
我认为这句话说得最清楚,“我试图在两个操作数中获得相同的类型”。
话虽这么说,但我不明白为什么有人会编写这段代码。如果没有有意义的 else 分支,那么语言中已经存在 if
结构,条件 ?:
运算符是错误的工具。
编辑:@walnut(现已删除)的回答实际上显示了一个用例:在 c++11 中,但在 c++14 之前,?:
运算符是表达条件分支的唯一方法在 constexpr 函数中。
我只见过 'old motorists' 的人编写的此类代码,或者可以这么说。 void()
调用基本上什么都不做,三元运算符要求您将 something 放在 else 分支中,因此人们有时会这样做。
if (stuff) { stuff->member(); }
也将是单行。
我发现 void();
在三元运算符的 'else' 分支中被用作 'do-nothing',作为空指针检查的 shorthand
if(var){ var->member(); }
作为
var ? var->member() : void();
但我似乎找不到以这种方式使用的 void
关键字的任何引用,这是对 void
关键字本身的函数或函子调用吗?或者它什么都不投射到 void
的类型?或者这只是 pass
?
编辑:
在这种情况下,member()
的 return 类型是 void
。
你只是在“构造”一个 void
类型的纯右值(不是变量,因为评论中建议的原因),就像 int()
默认构造一个 int
.
正如其他人在评论中所说,第二种选择是贬义的。三元运算符是 ternary,因为它具有 if
、then
和 else
部分。如果您不需要 else
,为什么要写一个并将其留空?
这个选择比这个更丑陋、更神秘:
if(var){
var->member();
} else {}
这可能看起来很愚蠢。
假设 var->member()
的类型为 void
,
var ? var->member() : void();
具有类型 void
,如果 var
为空,则计算 var->member()
或计算 void()
。
现在,void()
是一个表达式;根据 [expr.type.conv]/2
,它什么都不做:
if the type is cv
void
and the initializer is()
or{}
(after pack expansion, if any), the expression is a prvalue of the specified type that performs no initialization.
void
是一种类型,但如果它后面跟着 ()
,它会初始化 void
.
prvalue
原因,var->member()
的return类型是void
,第二个和第三个?:
运算符的操作数必须相同。注意:它们不必完全相同; conversion rules 表示类型何时可以不同。
您已经展示了一种为其中一个操作数获取 void
纯右值的方法,但是还有多种方法可以达到相同的效果,
var ? var->member() : throw 42;
a throw
表达式具有 void
类型,因此可以编译。当然,如果 var
是 nullptr
,它不会执行 nothing
,因为它会抛出。
此语句将编译但不执行任何操作,
var ? var->member() : []{}();
其中第二个操作数是匿名函数 returning void
.
还有这个,
var ? var->member() : decltype(var->member())();
我认为这句话说得最清楚,“我试图在两个操作数中获得相同的类型”。
话虽这么说,但我不明白为什么有人会编写这段代码。如果没有有意义的 else 分支,那么语言中已经存在 if
结构,条件 ?:
运算符是错误的工具。
编辑:@walnut(现已删除)的回答实际上显示了一个用例:在 c++11 中,但在 c++14 之前,?:
运算符是表达条件分支的唯一方法在 constexpr 函数中。
我只见过 'old motorists' 的人编写的此类代码,或者可以这么说。 void()
调用基本上什么都不做,三元运算符要求您将 something 放在 else 分支中,因此人们有时会这样做。
if (stuff) { stuff->member(); }
也将是单行。