In a C++ standard proposal, I find a strange code snippet as follows:
template <input_iterator I, sentinel_for<I> S, nothrow_forward_iterator I2>
constexpr auto uninitialized_copy(I first, S last, I2 d_first) -> I2 {
using T = iter_value_t<I2>;
I2 current = d_first;
try {
for (; first != last; ++first, (void)++current) {
::new (std::addressof(*current)) T(*first);
}
} catch (...) {
std::destroy(d_first, current);
throw;
}
}
Why use (void)++current
rather than just ++current
here?
++first, (void)++current
uses the comma operator ,
.
If ++first
evaluates to a type T
and ++current
to a type U
and there is a operator,
overload viable for T
/U
arguments, then this would call this operator,
overload.
However, it is not intended for it to be called. By making one of the two operands have type void
, it becomes impossible that an overload of ,
will be chosen and it will instead always have the built-in meaning.
That's why generic library code should always cast at least one operand to void
when using the comma operator.