When performing SFINAE on an arbitrary type, it's often necessary to cast the result of an expression to void
. I've seen two ways of doing this; a cast to void:
当对任意类型执行SFINAE时,通常需要将表达式的结果强制为void。我已经看到了两种方法;无效的演员:
(void)(expr) // or static_cast<void>(expr)
Or, alternatively, using the comma operator with a void prvalue RHS:
或者,也可以使用具有void 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; it is not possible in either case for even a pathological class T
to override T::operator void()
or operator,(T, void)
. (See: Why is "operator void" not invoked with cast syntax?, What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?).
我的理解是,在这两种情况下,expr都是被评估的(对于格式良好的情况,在未评估的环境中),而结果(或结果类型,在未评估的环境中)则被丢弃;无论哪种情况,即使是病理类T也不可能覆盖T::运算符void()或运算符(T, void)。(参见:为什么“操作符void”不使用强制转换语法调用?,自动f(params) ->解密(…空白())“做?)。
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 (e.g. understandability) to prefer one over the other?
这就是说,这两个习语是等价的吗?或者在任何情况下,一个人应该更倾向于另一个(可能是使用非标准的编译器)?如果没有,是否有什么原因(例如可理解性)让你更喜欢其中一个而不是另一个?
3 个解决方案
#1
2
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 - i.e.
因此,在考虑上述标准时,方法是等效的。记住这一点,我建议您在代码中使用更简洁的内容;但是无论你选择什么,都要坚持下去。我们还可以使用函数样式强制转换,因为在只有一个参数时,它的定义相当于显式强制转换符号—即。
auto g(auto f) -> decltype(void( f(1, 2, 3) ));
also works.
同样适用。
#2
1
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. For instance, foo + bar, void()
works just fine, but (void) (foo + bar)
(or the functional-style cast equivalent) will require parenthesizing the whole expression.
在某些情况下,由于逗号运算符的优先级较低,void()形式可以避免额外的一对括号。例如,foo + bar、void()工作得很好,但是(void) (foo + bar)(或函数样式的cast等效项)需要插入整个表达式。
In other cases, using a (void)
cast may be more concise. 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
.
在其他情况下,使用(void) cast可能更简洁。例如,为了防止+it1、+it2、+it3中的重载逗号,可以使用一个(void) cast - +it1、(void) +it2、+it2、+it3,但是要使用void()则需要编写两次:+it1、void()、+it2、void()、+it2、void()、+it3。
#3
0
Cast to void because comma can be overloaded.
由于逗号可以被重载,所以强制转换为void。
#1
2
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 - i.e.
因此,在考虑上述标准时,方法是等效的。记住这一点,我建议您在代码中使用更简洁的内容;但是无论你选择什么,都要坚持下去。我们还可以使用函数样式强制转换,因为在只有一个参数时,它的定义相当于显式强制转换符号—即。
auto g(auto f) -> decltype(void( f(1, 2, 3) ));
also works.
同样适用。
#2
1
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. For instance, foo + bar, void()
works just fine, but (void) (foo + bar)
(or the functional-style cast equivalent) will require parenthesizing the whole expression.
在某些情况下,由于逗号运算符的优先级较低,void()形式可以避免额外的一对括号。例如,foo + bar、void()工作得很好,但是(void) (foo + bar)(或函数样式的cast等效项)需要插入整个表达式。
In other cases, using a (void)
cast may be more concise. 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
.
在其他情况下,使用(void) cast可能更简洁。例如,为了防止+it1、+it2、+it3中的重载逗号,可以使用一个(void) cast - +it1、(void) +it2、+it2、+it3,但是要使用void()则需要编写两次:+it1、void()、+it2、void()、+it2、void()、+it3。
#3
0
Cast to void because comma can be overloaded.
由于逗号可以被重载,所以强制转换为void。