SFINAE:&#39; static_cast <void>()&#39;或&#39;,void()&#39;?</void>

时间:2015-03-03 16:48:57

标签: c++ void sfinae decltype

在任意类型上执行SFINAE时,通常需要将表达式的结果转换为void。我已经看到了两种方法;演员无效:

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

或者,使用带有void prvalue RHS的逗号运算符:

(expr), void()

我的理解是,在两种情况下expr都被评估(对于格式良好,在非评估的上下文中),结果(或结果类型,在非评估的上下文中)被丢弃;在任何一种情况下,即使是病态类T也无法覆盖T::operator void()operator,(T, void)。 (参见:Why is "operator void" not invoked with cast syntax?What does the 'void()' in 'auto f(params) -> decltype(..., void())' do?)。

那就是说,这两个成语是等价的,还是在某种情况下应该优先考虑另一个(可能是非标准的编译器)?如果没有,是否有任何理由(例如可理解性)更喜欢一个而不是另一个?

3 个答案:

答案 0 :(得分:2)

他们都符合所需的要求:

  • 要求expr作为废弃值表达式有效,仅作为
  • 始终具有类型void(用于跟踪返回类型或用于partial specializations

因此,当考虑上述标准时,这些方法是等效的。 牢记这一点,我建议您在代码中使用更简洁的内容;但无论你选择什么,都要坚持下去以保持一致 也可以使用函数样式转换,因为当只有一个参数时,它的定义等同于显式转换符号 - 即。

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

也有效。

答案 1 :(得分:1)

差异基本上是文体。

在某些情况下,由于逗号运算符的优先级较低,void()形式可以避免使用额外的括号。例如,foo + bar, void()工作正常,但(void) (foo + bar)(或函数式强制转换等效)将需要对整个表达式进行括号。

在其他情况下,使用(void)强制转换可能更简洁。例如,为了防止++it1, ++it2, ++it3中的重载逗号,您可以使用一个(void)强制转换 - ++it1, (void) ++it2, ++it3,但要使用void()则需要编写两次:{{1} }。

答案 2 :(得分:0)

转换为void,因为逗号可以重载。