Index: libs/algorithm/minmax/index.html =================================================================== RCS file: /cvsroot/boost/boost/libs/algorithm/minmax/index.html,v retrieving revision 1.4 diff -u -p -b -B -r1.4 index.html --- libs/algorithm/minmax/index.html 5 Oct 2004 15:45:16 -0000 1.4 +++ libs/algorithm/minmax/index.html 22 Nov 2004 11:30:29 -0000 @@ -1,4 +1,5 @@ - +
@@ -10,10 +11,10 @@ -++ - -Motivation
Synopsis
@@ -29,11 +30,10 @@ HREF="../../../../boost/minmax.hpp">boos Note about performance
Acknowledgements -
The minmax library is composed of two headers, minmax as straightforward extensions of the C++ standard. As it returns a pair of const&, we must use the Boost.tuple library to construct such -pairs. (Please note: the intent is not to fix the known defaults of +href="../../tuple/index.html">Boost.tuple
library to construct such +pairs. (Please note: the intent is not to fix the known faults of std::min -and std::max, but to add one more algorithms that combines both; see the +and std::max, but to add one more algorithm that combines both; see the rationale.)The second file implements the function templates @@ -81,22 +81,20 @@ all the minmax_element function 3n/2+1 comparisons and exactly n increments of the ForwardIterator.
- - -#include <boost/tuple/tuple.hpp> +#include <boost/tuple/tuple.hpp> namespace boost { - template <class T> - tuple<T const&, T const&> > + template <class T> + tuple<T const&, T const&> > minmax(const T& a, const T& b); - template <class T, class BinaryPredicate> - tuple<T const&, T const&> > + template <class T, class BinaryPredicate> + tuple<T const&, T const&> > minmax(const T& a, const T& b, BinaryPredicate comp); } @@ -105,16 +103,16 @@ namespace boost {Synopsis of <boost/algorithm/minmax_element.hpp>
-#include <utility> // for std::pair +#include <utility> // for std::pair namespace boost { - template <class ForwardIterator> - std::pair<ForwardIterator,ForwardIterator> + template <class ForwardIterator> + std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last); - template <class ForwardIterator, class BinaryPredicate> - std::pair<ForwardIterator,ForwardIterator> + template <class ForwardIterator, class BinaryPredicate> + std::pair<ForwardIterator,ForwardIterator> minmax_element(ForwardIterator first, ForwardIterator last, BinaryPredicate comp); @@ -134,10 +132,8 @@ which element(s) you want to pick in cas I won't bore you with the complete synopsis, they have exactly the same declaration as their corresponding _element function. Still, you can find the complete synopsis here. -
Last_min_element and last_max_element find the smallest and largest elements in the range [first, last). They are almost @@ -177,18 +173,14 @@ and the second version to:
Note: the first_min_last_max_element can also be described
as finding the first and last elements in the range if it were stably sorted.
-
int main() { using namespace std; - boost::tuple<int const&, int const&> result1 = boost::minmax(1, 0); + boost::tuple<int const&, int const&> result1 = boost::minmax(1, 0); assert( result1.get<0>() == 0 ); assert( result1.get<1>() == 1 ); - list<int> L; + list<int> L; generate_n(front_inserter(L), 1000, rand); - typedef list<int>::const_iterator iterator; - pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end()); + typedef list<int>::const_iterator iterator; + pair< iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end()); cout << "The smallest element is " << *(result2.first) << endl; cout << "The largest element is " << *(result2.second) << endl; assert( result2.first == std::min_element(L.begin(), L.end()); assert( result2.second == std::max_element(L.begin(), L.end()); }-
This was the design originally proposed and approved in the formal review. As the need for Boost.tuple became clear (due to the limitations of std::pair), it became also annoying to require another library for minmax_element which does not need it. Hence the separation into two header files.
- -I am aware of the problems with std::min and std::max, and all the debate that has been going on (please consult -Alexandrescu's -paper and the links therein). But I don't see the purpose of this +Alexandrescu's paper, + +"Min and Max Redivivus" and the links therein). But I don't see the purpose of this library as fixing something that is part of the C++ standard. I humbly think it's beyond the scope of this library. Rather, I am following the way of the standard in simply providing one more function of the same family. If someone else wants to fix std::min, their fix would probably apply to boost::minmax as well.
- -In a first version of the library, I proposed _if versions of all the algorithms (well, not all, because that would be too much). However, there is simply no reason to do so, and all the versions I had were just as fast implemented using the excellent -<boost/iterator_adaptors.hpp> library. Namely, a call to +<boost/iterator_adaptors.hpp> library. Namely, a call to min_element_if(first, last, pred) would be just as well implemented by: +
// equivalent to min_element_if(first, last, pred) min_element(boost::make_filter_iterator(first, last, pred), boost::make_filter_iterator(last, last, pred));+
Arguably, the min_element_if version is somewhat shorter, but the overhead of iterator adaptors is not large, and they get rid of a lot of code (think of all the combinations between first/last and doubling them with _if variants!).
-This rationale is somewhat historical, but explains why there are all these first/last_min/max_element functions.
The C++ standard mandates that std::min_element and std::max_element return the first instance of the smallest and largest elements (as opposed to, say, the last). This arbitrary choice has some consistency: In the -case of v of type vector<int>, for instance, it is true that std::min_element(v.begin(),v.end(),std::less<int>()) -== std::max_element(v.begin(),v.end(),std::greater<int>()). +case of v of type vector<int>, for instance, it is true that std::min_element(v.begin(),v.end(),std::less<int>()) +== std::max_element(v.begin(),v.end(),std::greater<int>()).
There is of course nothing wrong with this: it's simply a matter of choice. Yet another way to specify min_element and max_element is to define them as the first and the last elements if the range was stably sorted. (The stable sort is necessary to disambiguate between iterators that have the same value.) In that case, min should return the first instance and max should return the last. Then, both functions are related by -reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less<int>())) +reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less<int>())) == -std::last_max_element(v.rbegin(),v.rend(),std::greater<int>()). +std::last_max_element(v.rbegin(),v.rend(),std::greater<int>()). This definition is subtly different from the previous one.
The definition problem surfaces when one tries to design a minmax_element, using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction @@ -441,14 +422,14 @@ slower than and last_max_element called separately. [2] -
The minmax algorithms are useful in computing the extent of a range. In computer graphics, we need a bounding box of a set of objects. In that case the need for a single pass is even more stringent as all three directions must be done at once. Food for thoughts: there is matter for a nice generic programming library with stackable update_min and update_max function objects which store a reference to the -min_resultand +min_result and max_result variables, in conjunction with the for_each algorithm).
I believe many standard sequential algorithms could be reformulated @@ -458,12 +439,12 @@ do not see it competing with minmax, rat (including minmax) to the accumulator framework. However, I felt it is beyond the scope of this library to provide such accumulators.
- -True, and I could have gone that way, with the default policy for min_element and max_element to pick the first -occurence of the result. This would have thinned the number of +occurrence of the result. This would have thinned the number of combinations of the minmax_element variants. But it would also have meant to change the interface of boost::minmax_element. One of the goals of the minmax_element algorithm is its @@ -476,15 +457,12 @@ adding policies would have meant unfortu standard and created an obstacle towards that goal. Besides, the code remains rather readable and simple without policies. So I am quite happy to keep it like this. -
- + - -