minimax of input iterator range I previously posted a question on finding the maximum value of an InputIterator range. For completeness, I thought it would be useful to post an implementation that finds the minimum &amp; maximum values, in a similar way to std::minmax_element.

#include &lt;iterator&gt;
#include &lt;algorithm&gt;
#include &lt;functional&gt;
#include &lt;utility&gt;

namespace detail
{
    template &lt;typename InputIt, typename Compare&gt;
    auto minmax_input(InputIt first, InputIt last, Compare comp, std::input_iterator_tag)
    {
        using ValueType = typename std::iterator_traits&lt;InputIt&gt;::value_type;

        std::pair&lt;ValueType, ValueType&gt; result {*first, *first};

        if (++first == last) return result;

        if (comp(*first, result.first)) {
            result.first = *first;
        } else {
            result.second = *first;
        }

        while (++first != last) {
            auto prev = *first;
            if (++first == last) {
                if (comp(prev, result.first))
                    result.first = std::move(prev);
                else if (!comp(prev, result.second))
                    result.second = std::move(prev);
                break;
            } else {
                if (comp(*first, prev)) {
                    if (comp(*first, result.first))
                        result.first = *first;
                    if (!comp(prev, result.second))
                        result.second = std::move(prev);
                } else {
                    if (comp(prev, result.first))
                        result.first = std::move(prev);
                    if (!comp(*first, result.second))
                        result.second = *first;
                }
            }
        }

        return result;
    }

    template &lt;typename ForwardIt, typename Compare&gt;
    auto minmax_input(ForwardIt first, ForwardIt last, Compare comp, std::forward_iterator_tag)
    {
        const auto itr_result = std::minmax_element(first, last, comp);
        return std::make_pair(*itr_result.first, *itr_result.second);
    }
} // namespace detail

template &lt;typename InputIt, typename Compare = std::less&lt;void&gt;&gt;
auto minmax_input(InputIt first, InputIt last, Compare comp = Compare {})
{
    return detail::minmax_input(first, last, comp, typename std::iterator_traits&lt;InputIt&gt;::iterator_category {});
}


As this will presumably be used mostly on input streams, I also thought to provide this helper method:

#include &lt;istream&gt;

template &lt;typename T&gt;
auto minmax_stream(std::istream&amp; in)
{
    return minmax_input(std::istream_iterator&lt;T&gt; {in}, std::istream_iterator&lt;T&gt; {});
}


Used like:

#include &lt;iostream&gt;
#include &lt;sstream&gt;

int main()
{
    std::istringstream ss {"0.1 0.2 0.3 0.4 0.2 0.05 0.1"};

    const auto minmax = minmax_stream&lt;double&gt;(ss);

    std::cout &lt;&lt; "minmax is (" &lt;&lt; minmax.first &lt;&lt; ", " &lt;&lt; minmax.second &lt;&lt; ")" &lt;&lt; std::endl;
}
(This is an extended (and formatted…) comment (don't like the repetition of the non-pair comparisons at the beginning and end of the sequence). Not having used C++ in a dozen years, I'm hopeless with move semantics, for one. (And not quite destined to review C++ postings…))  

Let me try something about the non-pair comparisons:

template &lt;typename InputIt, typename Compare&gt;
auto minmax_input(InputIt first, InputIt last, Compare comp, std::input_iterator_tag)
{
    using ValueType = typename std::iterator_traits&lt;InputIt&gt;::value_type;

    auto const
        &amp;minimum = *first,
        &amp;maximum = minimum;

    while (++first != last) {
        auto &amp;prev = *first;
        if (++first == last) { // left with half a pair: prev
            if (comp(prev, minimum))
                minimum = prev;
            else if (!comp(prev, maximum))
                maximum = prev;
            break;
        }
        if (comp(*first, prev)) {
            if (comp(*first, minimum))
                minimum = *first;
            if (!comp(prev, maximum))
                maximum = prev;
        } else {
            if (comp(prev, minimum))
                minimum = prev;
            if (!comp(*first, maximum))
                maximum = *first;
        }
    }

    return std::pair&lt;ValueType, ValueType&gt; {minimum, maximum};
}


(Come to think of it, I don't like the symmetrical pairs of comparisons in the loop…)

        auto min_max = std::minmax(one, *first);
        if (comp(min_max.first, minimum))
            minimum = min_max.first;
        if (!comp(min_max.second, maximum))
            maximum = min_max.second;