std::transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>,
std::max_element(v.begin(), v.end()));
He later posted a correction, adding a dereference operator in
front of std::max_element. (This version has undefined
behavior, since the return value of std::max_element doesn't
meet the constraints on an argument to std::divides<double>. In
practice, I doubt that it will ever compile.)
[...]
Nope. The posted version seems to be missing the dereferencing of
max_element, which returns an iterator. If dereferencing is done, it will
have UB for empty vectors:
std::transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>,
* std::max_element(v.begin(), v.end()));
The point is that the dereferencing is done _before_
std::transform has a chance to tell that nothing needs to be
done.
It's easy enough to fix for the empty array case, so it would be
silly not to. Something like:
if ( ! v.empty() ) {
std::transform(v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>,
* std::max_element(v.begin(), v.end()));
}
or if you really want just a single statement:
v.empty()
? (void)0
: (void)std::transform(
v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>,
* std::max_element(v.begin(), v.end()));
or
v.empty()
? v.end()
: std::transform(
v.begin(), v.end(), v.begin(),
std::bind2nd(std::divides<double>,
* std::max_element(v.begin(), v.end()));
(Despite the higher statement count, I'd go with the first,
unless I needed the return value provided by the last---which
would be pretty surprising.)
Also, you could replace the "*std::max_element(v.begin(),
v.end())" subexpression with std::max( 1, *std::max_element...
to avoid undefined behavior, but I rather question the
usefulness of the resulting semantics. Something like:
*std::max_element( ... ) == 0
? throw someDocumentedError
: *std::max_element( ... )
would do the trick, but it seems overdoing the "avoid premature
optimization" rule, even to me, since it iterates over the
entire vector twice, when once would do. (Theoretically, I
guess, a compiler could optimize out the second iteration, but
it would take some doing, and I rather doubt that any do. And
the implementation cannot even use a compiler specific
annotation to tell the compiler that max_element is a pure
function, since it's a template, and if any of the actions on
the iterators have side effects, it's not.)