I came across this SO question on why std::max_element
requires a ForwardIterator
(as apposed to an InputIterator
). Having a max_element
-like algorithm for InputIterator
would be useful, as it could then be used with objects like std::istream_iterator
or boost::transform_iterator
.
I came up with the following algorithm for this:
#include <iterator> // std::iterator_traits, std::advance
#include <stdexcept> // std::logic_error
#include <algorithm> // std::for_each
#include <functional> // std::less
#include <utility> // std::move
template <typename InputIterator, typename Compare>
typename std::iterator_traits<InputIterator>::value_type
max_input(InputIterator first, InputIterator last, Compare comp)
{
if (first == last) throw std::logic_error {"max_input given empty range"};
using ValueType = typename std::iterator_traits<InputIterator>::value_type;
ValueType result {*first};
std::advance(first, 1);
std::for_each(first, last, [&result, comp] (ValueType curr) {
if (comp(result, curr)) result = std::move(curr);
});
return result;
}
Example:
#include <sstream>
#include <iostream>
int main()
{
std::istringstream str("0.1 0.2 0.3 0.4 0.2 0.0 0.1");
const auto max = max_input(std::istream_iterator<double>(str), std::istream_iterator<double>());
std::cout << "max is " << max << std::endl;
return 0;
}
I'm looking for general feedback/improvements, especially on the decision to throw
for an empty range. I was also deliberating whether the algorithm should also return the index of the maximum (e.g. in a std::pair
).