SFINAE: 'static_cast<void>()' or ', void()'?
Asked Answered
U

3

9

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:

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

Or, alternatively, using the comma operator with a 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?).

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?

Unhitch answered 3/3, 2015 at 16:48 Comment(1)
I would just use the shortest and most clear notation. If there should be any subtlety that would force use of the comma expression, I'd use that for that specific case, with a comment explaining why. I can't think of any such subtlety though.Orthodontia
G
2

They both meet the requirements needed:

  • Require that expr be valid as a discarded-value expression, and only that.
  • Always have type void (for use in trailing return types or for partial specializations)

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.

Gahnite answered 3/3, 2015 at 17:12 Comment(0)
H
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.

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.

Heiduc answered 3/3, 2015 at 20:6 Comment(0)
T
0

Cast to void because comma can be overloaded.

Taam answered 22/9, 2017 at 11:25 Comment(2)
There's a whole paragraph which shows that OP does know why these patterns exist. He's asking for a comparison between them.Sutlej
The comma operator cannot be overloaded where either of the operands is void.Unhitch

© 2022 - 2024 — McMap. All rights reserved.