SFINAE: 'static_cast <void> ()' or ', void ()'?
When executing SFINAE on an arbitrary type, it is often necessary to pass the result of the expression to void . I have seen two ways to do this; cast into the void:
(void)(expr) // or static_cast<void>(expr) Or, alternatively, using a comma operator with void prvalue RHS:
(expr), void() I understand that in both cases expr is evaluated (for correctness, in an undefined context), and the result (or the type of result in an unvalued context) is discarded; in any case, it is impossible even for pathological class T override T::operator void() or operator,(T, void) . (See: Why is the βstatement invalidβ not called with the translation syntax? What does βvoid ()β mean in 'auto f (params) β decltype (..., void ())' do? ).
However, are these two idioms equivalent, or are there any circumstances in which preference should be given to another (possibly with non-standard compilers)? If not, are there any reasons (e.g. clarity) to prefer each other?
They meet the requirements of:
- Require
exprbe valid as an expression with a discarded value, and only that. - Always be of type
void(for use in trailing return types or for partial specializations )
Thus, when considering the above criteria, the methods are equivalent. With this in mind, I would recommend using anything that is more concise in your code; but whatever you choose, stick to it for consistency.
You can also use the functional style, as it is by definition equivalent to explicit letter notation when there is only one argument - i.e.
auto g(auto f) -> decltype(void( f(1, 2, 3) )); also works.
The difference is mostly stylistic.
In some cases, due to the low priority of the comma operator, the void() form can avoid an extra pair of parentheses. For example, foo + bar, void() works just fine, but (void) (foo + bar) (or the equivalent of a functional style equivalent) will require brackets for the whole expression.
In other cases, use (void) 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() you will need to write it twice: ++it1, void(), ++it2, void(), ++it3 .
It is thrown into the void because the comma may be overloaded.