Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/algorithm/minmax/index.html @ 12

Last change on this file since 12 was 12, checked in by landauf, 18 years ago

added boost

File size: 23.9 KB
Line 
1<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
2<HTML>
3<HEAD>
4   <LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
5   <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6   <META name="GENERATOR" content="Mozilla/4.77 [en] (X11; U; Linux 2.2.19 i686) [Netscape]">
7   <META name="Author" content="Herve Bronnimann">
8   <META name="Description" content="Small library to propose minmax_element algorithm.">
9   <title>Boost Minmax library</title>
10</HEAD>
11<body text="#000000" bgcolor="#FFFFFF" link="#0000EE" vlink="#551A8B" alink="#FF0000">
12
13<h2><img src="../../../boost.png" WIDTH="276" HEIGHT="86">Header &lt;<A
14HREF="../../../boost/algorithm/minmax.hpp">boost/algorithm/minmax.hpp</A>&gt; </H2>
15
16<quote>
17<b>
18<a href="#minmax_element">Motivation</a><br>
19<a href="#synopsis">Synopsis</a><br>
20<a href="#description">Function templates description</a><br>
21<a href="#definition">Definition</a><br>
22<a href="#reqs">Requirements on types</a><br>
23<a href="#precond">Preconditions</a><br>
24<a href="#postcond">Postconditions</a><br>
25<a href="#complexity">Complexity</a><br>
26<a href="#example">Example</a><br>
27<a href="#notes">Notes</a><br>
28<a href="#rationale">Rationale</a><br>
29<a href="#perf">Note about performance</a><br>
30<a href="#acks">Acknowledgements</a>
31</b>
32</quote>
33
34
35<a name="minmax_element">
36<h3>
37Motivation</h3>
38
39<p>The minmax library is composed of two headers, <a
40href="../../../boost/algorithm/minmax.hpp">&lt;boost/algorithm/minmax.hpp></a>
41and <a
42href="../../../boost/algorithm/minmax_element.hpp">&lt;boost/algorithm/minmax_element.hpp></a>.
43(See <a href="#two_headers">rationale</a>.)
44The problem solved by this library is that simultaneous min and max
45computation requires
46only one comparison, but using <tt>std::min</tt> and <tt>std::max</tt>
47forces two comparisons. Worse, to compute the minimum and
48maximum elements of a range of <tt>n</tt> elements requires only
49<tt>3n/2+1</tt> comparisons, instead of the <tt>2n</tt> (in two passes)
50forced by <tt>std::min_element</tt> and <tt>std::max_element</tt>.
51I always thought it is a waste to have to call two functions to compute the
52extent of a range, performing two passes over the input, when one should
53be enough. The present library solves both problems.</p>
54
55<p>The first file implements the function templates
56<tt>minmax</tt>
57as straightforward extensions of the C++
58standard. As it returns a pair of <tt>const&amp;</tt>, we must use the <a
59href=:../../../../tuple/index.html>Boost.tuple</a> library to construct such
60pairs. (Please note: the intent is not to fix the known defaults of
61<tt>std::min</tt>
62and <tt>std::max</tt>, but to add one more algorithms that combines both; see the
63<a href="#no-fix">rationale</a>.)</p>
64
65<p>The second file implements the function templates
66<tt>minmax_element</tt>. In a
67second part, it also proposes variants that can usually not be computed by
68the minmax algorithm, and which are more flexible in case some elements are equal.
69Those variants could have been also provided with policy-based design,
70but I ruled against that (see <a href="#no-policy">rationale</a>).
71</p>
72
73<p>If you are interested about
74<a href="doc/minmax_benchs.html">performance</a>,
75you will see that <tt>minmax_element</tt> is just slightly less efficient
76than a single <tt>min_element</tt> or <tt>max_element</tt>, and thus
77twice as efficient as two separate calls to <tt>min_element</tt> and
78<tt>max_element</tt>. From a
79theoretical standpoint,
80all the <tt>minmax_element</tt> functions perform at most
81<tt>3n/2+1</tt>
82comparisons and exactly n increments of the
83<tt>ForwardIterator</tt>.</p>
84</a>
85
86<a name="synopsis">
87<h3>
88Synopsis of <tt>&lt;boost/algorithm/minmax.hpp></tt></h3>
89
90<pre>#include &lt;boost/tuple/tuple.hpp>
91
92namespace boost {
93
94  template &lt;class T>
95  tuple&lt;T const&amp;, T const&amp;> >
96  minmax(const T&amp; a, const T&amp; b);
97
98  template &lt;class T, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
99  tuple&lt;T const&amp;, T const&amp;> >
100  minmax(const T&amp; a, const T&amp; b, BinaryPredicate comp);
101
102}
103</pre>
104
105<h3>
106Synopsis of <tt>&lt;boost/algorithm/minmax_element.hpp></tt></h3>
107
108<pre>#include &lt;utility> // for std::pair
109
110namespace boost {
111
112  template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>>
113  std::pair&lt;ForwardIterator,ForwardIterator>
114  minmax_element(ForwardIterator first, ForwardIterator last);
115
116  template &lt;class <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>, class <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">BinaryPredicate</a>>
117  std::pair&lt;ForwardIterator,ForwardIterator>
118  minmax_element(ForwardIterator first, ForwardIterator last,
119                 BinaryPredicate comp);
120
121}
122</pre>
123
124In addition, there are a bunch of extensions which specify
125which element(s) you want to pick in case of equal elements. They are:
126<ul>
127<li><tt>first_min_element</tt> and <tt>last_min_element</tt></li>
128<li><tt>first_max_element</tt> and <tt>last_max_element</tt></li>
129<li><tt>first_min_first_max_element</tt>,
130<tt>first_min_last_max_element</tt>,
131<tt>last_min_first_max_element</tt>, and
132<tt>last_min_last_max_element</tt></li>
133</ul>
134I won't bore you with the complete synopsis, they have exactly the same
135declaration as their corresponding <tt>_element</tt> function. Still,
136you can find the complete synopsis <a href="doc/minmax_synopsis.html">here</a>.
137</a>
138
139<a name="description">
140<h3>
141Function templates description</h3>
142The <tt>minmax</tt> algorithm returns a pair <tt>p</tt> containing either
143<i>(a,b)</i>
144or <i>(b,a)</i>, such that <tt>p.first&lt;p.second</tt> in the first version,
145or <tt>comp(p.first,p.second)</tt> in the second version. If the elements
146are equivalent, the pair <i>(a,b) </i>is returned. <a href="#Note1">[1]</a>
147<p>The <tt>minmax_element </tt>is semantically equivalent to <tt>first_min_first_max_element</tt>.
148<p><tt>First_min_element</tt> and <tt>first_max_element</tt> find the smallest
149and largest elements in the range <tt>[first, last)</tt>. If there are
150several instance of these elements, the first one is returned. They are
151identical to
152<tt>std::min_element</tt> and <tt>std::max_element</tt>and
153are only included in this library for symmetry.
154<p><tt>Last_min_element</tt> and <tt>last_max_element</tt> find the smallest
155and largest elements in the range <tt>[first, last)</tt>. They are almost
156identical to
157<tt>std::min_element</tt> and <tt>std::max_element</tt>, except
158that they return the last instance of the largest element (and not the
159first, as <tt>first_min_element</tt> and <tt>last_max_element</tt> would).
160<p>The family of algorithms comprising <tt>first_min_first_max_element</tt>,
161<tt>first_min_first_max_element</tt>,
162<tt>first_min_first_max_element</tt>,
163and <tt>first_min_first_max_element</tt> can be described generically as
164follows (using <i><tt>which</tt></i> and
165<i><tt>what</tt></i> for <tt>first</tt>
166or <tt>last</tt>): <tt><i>which</i>_min_<i>what</i>_max_element</tt> finds
167the (first or last, according to <i><tt>which</tt></i>) smallest element
168and the (first or last, according to <i><tt>what</tt></i>) largest element
169in the range
170<tt>[first, last)</tt>. The first version is semantically
171equivalent to:
172<pre><tt>  std::make_pair(boost::<i>which</i>_min_element(first,last),
173                 boost::<i>what</i>_max_element(first,last))</tt>,</pre>
174and the second version to:
175<pre><tt>  std::make_pair(boost::<i>which</i>_min_element(first,last,comp),
176                 boost::<i>what</i>_max_element(first,last,comp))</tt>.</pre>
177
178<p><br><b><i>Note</i></b>: the <tt>first_min_last_max_element</tt> can also be described
179as finding the first and last elements in the range if it were stably sorted.
180</a>
181
182<a name="definition">
183<h3>
184Definition</h3>
185Defined in <a href="../../../boost/algorithm/minmax.hpp">minmax.hpp</a>
186and
187in <a href="../../../boost/algorithm/minmax_element.hpp">minmax_element.hpp</a>.
188</a>
189
190<a name="reqs">
191<h3>
192Requirements on types</h3>
193For minmax, <tt>T</tt> must be a model of <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
194Comparable</a>.
195<p>For all the other function templates, versions with two template parameters:
196<ul>
197<li>
198<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
199Iterator</a>.</li>
200
201<li>
202<tt>ForwardIterator</tt>'s value type is <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
203Comparable</a>.</li>
204</ul>
205For the versions with three template parameters:
206<ul>
207<li>
208<tt>ForwardIterator</tt> is a model of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
209Iterator</a>.</li>
210
211<li>
212<tt>BinaryPredicate</tt> is a model of <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
213Predicate</a>.</li>
214
215<li>
216<tt>ForwardIterator</tt>'s value type is convertible to <tt>BinaryPredicate</tt>'s
217first argument type and second argument type.</li>
218</ul>
219</a>
220
221<a name="precond">
222<h3>
223Preconditions</h3>
224
225<ul>
226<li>
227<tt>[first, last)</tt> is a valid range.</li>
228</ul>
229</a>
230
231<a name="postcond">
232<h3>
233Postconditions</h3>
234In addition to the semantic description above. for <tt>minmax_element</tt>
235and all the <tt><i>which</i>_min_<i>what</i>_max_element</tt>
236variants, the return value is
237<tt>last</tt> or <tt>std::make_pair(last,last)</tt>
238if and only if <tt>[first, last)</tt> is an empty range. Otherwise, the
239return value or both members of the resulting pair are iterators in the
240range
241<tt>[first, last)</tt>.
242</a>
243
244<a name="complexity">
245<h3>
246<a NAME="Complexity"></a>Complexity</h3>
247Minmax performs a single comparison and is otherwise of constant complexity.
248The use of <tt>boost::tuple&lt;T const&amp;></tt> prevents copy
249constructors in case the arguments are passed by reference.
250<p>The complexity of all the other algorithms is linear. They all perform
251exactly n increment operations, and zero comparisons if <tt>[first,last)</tt>
252is empty, otherwise :
253<ul>
254<li>
255all the <tt>min_element</tt> and <tt>max_element</tt> variants perform
256exactly<tt>(n-1)</tt> comparisons,</li>
257
258<li>
259<tt>minmax_element</tt> , <tt>first_min_first_max_element</tt>, and <tt>last_min_last_max_element</tt>
260perform at most <tt>3(n/2)-1</tt> comparisons if <tt>n</tt> is even and
261non-zero, and at most <tt>3(n/2)+1</tt> if <tt>n</tt> is odd,
262<a href="#Note2">[2]</a></li>
263
264<li>
265<tt>first_min_last_max_element</tt>, and <tt>last_min_first_max_element</tt>
266perform exactly <tt>3n/2-2</tt> comparisons if n is even and non-zero,
267and at most <tt>3(n/2)</tt> if <tt>n</tt> is odd,
268<a href="#Note1">[3]</a></li>
269</ul>
270where <tt>n</tt> is the number of elements in <tt>[first,last)</tt>.
271</a>
272
273<a name="example">
274<h3>
275Example</h3>
276This example is included in the distribution in the examples section of
277the library under
278<a href="example/minmax_ex.cpp">minmax_ex.cpp</a>.
279
280<pre>int main()
281{
282  using namespace std;
283  boost::tuple&lt;int const&amp;, int const&amp;> result1 = boost::minmax(1, 0);
284
285  assert( result1.get<0>() == 0 );
286  assert( result1.get<1>() == 1 );
287
288  <a href="http://www.sgi.com/tech/stl/List.html">list</a>&lt;int> L;
289  <a href="http://www.sgi.com/tech/stl/generate_n.html">generate_n</a>(<a href="http://www.sgi.com/tech/stl/front_insert_iterator.html">front_inserter</a>(L), 1000, rand);
290
291  typedef list&lt;int>::const_iterator iterator;
292  pair&lt; iterator, iterator > result2 = boost::minmax_element(L.begin(), L.end());
293  cout &lt;&lt; "The smallest element is " &lt;&lt; *(result2.first) &lt;&lt; endl;
294  cout &lt;&lt; "The largest element is  " &lt;&lt; *(result2.second) &lt;&lt; endl;
295
296  assert( result2.first  == std::min_element(L.begin(), L.end());
297  assert( result2.second == std::max_element(L.begin(), L.end());
298}</pre>
299</a>
300
301<a name="notes">
302<h3>
303Notes</h3>
304<a NAME="Note1"></a><a href="#Note1">[1]</a> We do not support
305idioms such as <tt><a href="../../tuple/doc/tuple_users_guide.html#tiers">tie</a>(a,b)=minmax(a,b)</tt>
306to order two elements <tt>a</tt>, <tt>b</tt>, although this would have
307the desired effect if we returned a reference instead of a constant
308reference. The reason is that two unnecessary assignments are
309performed if a and b are in order. It is better to stick to <tt>if (b&lt;a)
310swap(a,b)</tt> to achieve that effect.
311<p><a NAME="Note2"></a><a href="#Note2">[2]</a> These algorithms always
312perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
313the number of comparisons in any case (Cormen, Leiserson, Rivest: "Introduction
314to Algorithms", section 9.1, Exercise 9.1-). The algorithms essentially compare
315the elements in pairs, performing 1 comparison for the first two elements,
316then 3 comparisons for each remaining pair of elements (one to order the
317elements and one for updating each the minimum and and the maximum). When
318the number of elements is odd, the last one needs to be compared to the
319current minimum and also to the current maximum. In addition, for <tt>minmax</tt>,
320in cases where equality of the two members in the pair could occur, and
321the update stores the second, we save the first to check at the end if
322the update should have stored the first (in case of equality). It's hard
323to predict if the last comparison is performed or not, hence the at most
324in both cases.
325<p><a NAME="Note3"></a><a href="#Note3">[3]</a> These algorithms always
326perform at least <tt>3n/2-2</tt> comparisons, which is a lower bound on
327the number of comparisons in any case. The method is the same as in note
328<a href="#Note2">[2]</a>
329above, and like above, when the number of elements is odd, the last one
330needs to be compared to the current minimum and also to the current maximum.
331We can avoid the latter comparison if the former is successful, hence the
332<i>at
333most</i> instead of <i>exactly</i> in the odd case.
334</a>
335
336<a name="rationale">
337<h3>
338<b>Rationale:</b></h3>
339
340<a name="two_headers">
341<h4><b>Why not a single header <tt>&amp;boost/algorithm/minmax.hpp></tt>?</b></h4>
342<p>This was the design originally proposed and approved in the formal
343review. As the need for Boost.tuple became clear (due to the limitations
344of <tt>std::pair</tt>), it became also annoying to require another
345library for <tt>minmax_element</tt> which does not need it. Hence the
346separation into two header files.</p>
347
348<a name="no-fix">
349<h4><b>Your minmax suffers from the same problems as std::min and
350std::max.</b></h4>
351<p>I am aware of the problems with std::min and
352std::max, and all the debate that has been going on (please consult
353<a href="http://www.cuj.com/experts/1904/alexandr.htm?topic=experts&topic=experts">Alexandrescu's
354paper</a> and the links therein). But I don't see the purpose of this
355library as fixing something that is part of the C++ standard. I humbly
356think it's beyond the scope of this library. Rather, I am
357following the way of the standard in simply providing one more function
358of the same family. If someone else wants to fix std::min, their fix
359would probably apply to boost::minmax as well.</p>
360</a>
361
362<h4><b>Why no <tt>min/max_element_if</tt>?</b></h4>
363<p>In a first version of the library, I proposed <tt>_if</tt> versions of
364all the algorithms (well, not all, because that would be too much).
365However, there is simply no reason to do so, and all the versions I had
366were just as fast implemented using the excellent
367<tt>&lt;boost/iterator_adaptors.hpp></tt> library. Namely, a call to
368<tt>min_element_if(first, last, pred)</tt> would be just as well
369implemented by:
370<pre>
371     // equivalent to min_element_if(first, last, pred)
372     min_element(boost::make_filter_iterator(first, last, pred),
373                 boost::make_filter_iterator(last, last, pred));
374</pre>
375Arguably, the <tt>min_element_if</tt> version is somewhat shorter, but
376the overhead of iterator adaptors is not large, and they get rid of a
377lot of code (think of all the combinations between first/last and
378doubling them with _if variants!).</p>
379
380<h4><b>Discussion: about std::max_element</b></h4>
381<p>This rationale is somewhat historical, but explains why there are all
382these <tt>first/last_min/max_element</tt> functions.</p>
383<p>The C++ standard mandates that <tt>std::min_element</tt> and <tt>std::max_element</tt>
384return the first instance of the smallest and largest elements (as opposed
385to, say, the last). This arbitrary choice has some consistency: In the
386case of v of type vector&lt;int>, for instance, it is true that <tt>std::min_element(v.begin(),v.end(),std::less&lt;int>())
387== std::max_element(v.begin(),v.end(),std::greater&lt;int>())</tt>.
388<p>There is of course nothing wrong with this: it's simply a matter of
389choice. Yet another way to specify min_element and max_element is to define
390them as the first and the last elements if the range was stably sorted.
391(The <i>stable</i> sort is necessary to disambiguate between iterators
392that have the same value.) In that case, min should return the first instance
393and max should return the last. Then, both functions are related by
394<tt>reverse_iterator(std::first_min_element(v.begin(),v.end(),std::less&lt;int>()))
395==
396std::last_max_element(v.rbegin(),v.rend(),std::greater&lt;int>())</tt>.
397This definition is subtly different from the previous one.</p>
398<p>The definition problem surfaces when one tries to design a minmax_element,
399using the procedure proposed in (Cormen, Leiserson, Rivest: "Introduction
400to Algorithms", section 9.1). It <i>should</i> be possible to derive an
401algorithm using only <tt>3n/2</tt> comparisons if <tt>[first,last) </tt>has
402<tt>n</tt>
403elements, but if one tries to write a function called <tt>first_min_first_max_element()</tt>
404which returns both <tt>std::min_element</tt> and <tt>std::max_element</tt>
405in a pair, the trivial implementation does not work. The problem, rather
406subtly, is about equal elements: I had to think for a while to find a
407way to perform only three
408comparisons per pair and return the first min and first max elements.
409For a long time, it seemed any
410attempts at doing so would consume four comparisons per pair in the worst
411case. This implementation achieves three.</p>
412<p>It is not possible (or even desirable) to change the meaning of
413<tt>max_element</tt>,
414but it is still beneficial to provide a function called <tt>minmax_element</tt>,
415which returns a pair of <tt>min_element</tt> and <tt>max_element</tt>.
416Although it is easy enough to call <tt>min_element</tt> and <tt>max_element</tt>,
417this performs
418<tt>2(n-1)</tt> comparisons, and necessitates <b>two</b>
419passes over the input. In contrast,
420<tt>minmax_element</tt> will perform
421the fewer comparisons and perform a <b>single</b> pass over the input.
422The savings can be significant when the iterator type is not a raw pointer,
423or even is just a model of the InputIterator concept (although in that
424case the interface would have to be
425changed, as the return type could not be copied, so one could e.g.
426return a value).</p>
427<p>In order to benefit from all the variants of the algorithm, I propose
428to introduce both <tt>first_min_element</tt> and <tt>last_min_element</tt>,
429and their counterparts <tt>first_max_element</tt> and <tt>last_max_element</tt>.
430Then I also propose all the variants algorithms: <tt>first_min_last_max_element</tt>
431and <tt>last_min_first_max_element</tt>, which perform only at most <tt>3n/2</tt>
432comparisons, and only a single pass on the input. In fact, it can be proven
433that computing minmax requires at least <tt>3(n/2)-2</tt> comparisons in
434any instance of the problem (Cormen, Leiserson, Rivest, 2nd edition, section
4359.1). The implementation I give does not perform unnecessary comparisons
436(whose result could have been computed by transitivity from previous
437comparisons).</p>
438<p>It appears that <tt>first_min_last_max_element</tt> may be just a tad
439slower than
440<tt>first_min_element</tt> alone, still much less than <tt>first_min_element</tt>
441and
442<tt>last_max_element</tt> called separately.  <a href="#Performance">[2]</a>
443
444<h4><b>Why algorithms and not accumulators?</b></h4>
445<p>The minmax algorithms are useful in computing the extent of a range.
446In computer graphics, we need a bounding box of a set of objects.
447In that case the need for a single pass is even more stringent
448as all three directions must be done at once. Food for thoughts: there
449is matter for a nice generic programming library with stackable <tt>update_min</tt>
450and <tt>update_max</tt> function objects which store a reference to the
451<tt>min_result</tt>and
452<tt>max_result</tt> variables, in conjunction with the <tt>for_each</tt>
453algorithm).</p>
454<p>I believe many standard sequential algorithms could be reformulated
455with accumulators (and many others, such as in statistics, expectation /
456variance / etc.). It seems that there is room for another library, but I
457do not see it competing with minmax, rather extending several algorithms
458(including minmax) to the accumulator framework. However, I felt it is
459beyond the scope of this library to provide such accumulators.</p>
460
461<a NAME="no-policy">
462<h4><b>This first/last is a perfect application for a policy-based
463design.</b></h4>
464<p>True, and I could have gone that way, with the default policy for
465<tt>min_element</tt> and <tt>max_element</tt> to pick the first
466occurence of the result. This would have thinned the number of
467combinations of the minmax_element variants. But it would also have
468meant to change the interface of <tt>boost::minmax_element</tt>.
469One of the goals of the <tt>minmax_element</tt> algorithm is its
470eventual addition to the C++ standard, in connection with
471<tt>std::min_element</tt> and <tt>std::max_element</tt>
472(and I feel that it would be quite natural
473given the shortness of the implementation, and the not quite trivial
474detail which is needed to get it right). So changing the interface by
475adding policies would have meant unfortunately to depart from the
476standard and created an obstacle towards that goal. Besides, the code
477remains rather readable and simple without policies. So I am quite happy
478to keep it like this.
479</p></a>
480</a>
481
482<a name="perf">
483<a href="doc/minmax_benchs.html"><h3><b>About performance</b></h3></a>
484</a>
485
486<a name="acks">
487<h3>
488Acknowledgements</h3>
489My students in CS903 (Polytechnic Univ., <a href="http://photon.poly.edu/~hbr/cs903/">http://photon.poly.edu/~hbr/cs903/</a>)
490who had <tt>minmax_element</tt> as an assignment helped clarify the issues,
491and also come up with the optimum number of comparisons for <tt>first_min_last_max_element</tt>.
492The identification of the issue surrounding <tt>max_element</tt> is solely
493my own.
494<p>One <tt>minmax_element</tt> implementation, which performs <tt>3(n/2)+O(log
495n)</tt> comparisons on the average when the elements are <tt>random_shuffle</tt>d,
496was suggested by my student Marc Glisse. The current one, which performs
497<tt>3(n/2)+1</tt>
498comparisons in the worst case, was suggested by John Iacono.<p>
499<p>Finally, Matthew Wilson and Jeremy Siek contributed pre-review
500comments, while Gennadiy Rozental, John Maddock, Craig Henderson, Gary
501Powell participated in the review of the library, managed by Thomas
502Witt. In particular, Gennadiy suggested a factorization of the code;
503while I haven't followed it all the way, his suggestions do make the
504code more readable and still work with older compilers.
505Late after the review, as I finally scrounged to add the library for a
506release, Eric Niebler noted the bad behavior of <tt>std::pair</tt> for
507<tt>minmax</tt> and suggested to use Boost.tuple instead.
508All my thanks for the excellent advice and reviews from all.
509<h3>
510See also</h3>
511<tt><a href="http://www.sgi.com/tech/stl/min.html">min</a></tt>, <tt><a href="http://www.sgi.com/tech/stl/max.html">max</a></tt>,
512<tt><a href="http://www.sgi.com/tech/stl/min_element.html">min_element</a></tt>,
513<tt><a href="http://www.sgi.com/tech/stl/max_element.html">max_element</a></tt>,
514<tt><a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThan
515Comparable</a></tt>,
516<tt><a href="http://www.sgi.com/tech/stl/sort.html">sort</a></tt>,
517<tt><a href="http://www.sgi.com/tech/stl/nth_element.html">nth_element</a></tt>
518.
519<hr SIZE="6">
520<br>Last modified 2004-07-01
521<p><font face="Arial,Helvetica"><font size=-1>&copy; Copyright Herv&eacute;
522Br&ouml;nnimann, Polytechnic University, 2002--2004.
523Use, modification, and distribution is subject to the Boost Software
524License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">License_1_0.txt</a> or copy at
525<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)
526</font></font>
527</body>
528</html>
Note: See TracBrowser for help on using the repository browser.