简体   繁体   English

SFINAE:“ static_cast <void> ()”或“,void()”?

[英]SFINAE: 'static_cast<void>()' or ', void()'?

When performing SFINAE on an arbitrary type, it's often necessary to cast the result of an expression to void . 在对任意类型执行SFINAE时,通常需要将表达式的结果强制转换为void I've seen two ways of doing this; 我已经看到了两种方法来做到这一点; a cast to void: 投向虚空:

(void)(expr)    // or static_cast<void>(expr)

Or, alternatively, using the comma operator with a void prvalue RHS: 或者,或者将逗号运算符与无效prvalue RHS结合使用:

(expr), void()

It's my understanding that in both cases expr is evaluated (for well-formedness, in a non-evaluated context) and the result (or result type, in a non-evaluated context) discarded; 我的理解是,在两种情况下都对expr进行了评估(在未评估的情况下为良好的格式),而结果(或在未评估的情况下为结果类型)都被丢弃了; it is not possible in either case for even a pathological class T to override T::operator void() or operator,(T, void) . 在任何情况下,即使是病理类T无法覆盖T::operator void()operator,(T, void) (See: Why is "operator void" not invoked with cast syntax? , What does the 'void()' in 'auto f(params) -> decltype(..., void())' do? ). (请参阅: 为什么不使用强制转换语法调用“运算符void” ?“自动f(参数)-> decltype(...,void())”中的“ void()”有什么作用? )。

That said, are these two idioms equivalent, or are there any circumstances under which one should be preferred to the other (possibly with nonstandard compilers)? 就是说,这两个习惯用法是等效的,还是在任何情况下都应该优先使用另一个(可能是非标准编译器)? If not, are there any reasons (eg understandability) to prefer one over the other? 如果不是,是否有任何理由(例如,可理解性)偏爱另一个?

They both meet the requirements needed: 它们都满足所需的要求:

  • Require that expr be valid as a discarded-value expression, and only that. 要求expr作为舍弃值表达式有效, 而已
  • Always have type void (for use in trailing return types or for partial specializations ) 始终具有void类型(用于尾随返回类型或部分专业化

Thus the methods are equivalent when considering the above criteria. 因此,在考虑上述标准时,这些方法是等效的。 Keeping that in mind, I'd recommend to use whatever is more concise in your code; 记住这一点,我建议您使用代码中更简洁的内容。 but whatever you choose, stick to it for consistency. 但是无论您选择什么,都必须坚持下去以保持一致性。
One can also use a functional style cast, since it is by definition equivalent to the explicit cast notation when there is only one argument - ie 也可以使用一种功能样式转换,因为在只有一个参数的情况下,按定义它等同于显式转换符号-即

auto g(auto f) -> decltype(void( f(1, 2, 3) ));

also works. 也可以。

The difference is basically stylistic. 区别基本上是风格上的。

In some cases, due to the low precedence of the comma operator, the void() form can avoid an extra pair of parentheses. 在某些情况下,由于逗号运算符的优先级较低,因此void()形式可以避免使用多余的一对括号。 For instance, foo + bar, void() works just fine, but (void) (foo + bar) (or the functional-style cast equivalent) will require parenthesizing the whole expression. 例如, foo + bar, void()可以很好地工作,但是(void) (foo + bar) (或等效的功能样式转换)将需要用括号括住整个表达式。

In other cases, using a (void) cast may be more concise. 在其他情况下,使用(void)强制转换可能更简洁。 For example, to protect against overloaded commas in ++it1, ++it2, ++it3 , you can use one (void) cast - ++it1, (void) ++it2, ++it3 , but to use void() would require writing it twice: ++it1, void(), ++it2, void(), ++it3 . 例如,要防止++it1, ++it2, ++it3逗号过载,可以使用一个(void) ++it1, (void) ++it2, ++it3 - ++it1, (void) ++it2, ++it3 ,但要使用void()将需要编写两次: ++it1, void(), ++it2, void(), ++it3

强制转换为空,因为逗号可以重载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM