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?
They both meet the requirements needed:
expr
be valid as a discarded-value expression, and only that.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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With