<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>max()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="mask-array.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="max-element.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library Reference Guide</B></DIV>
<H2>max()</H2>
<P><B>Library:</B>&nbsp;&nbsp;<A HREF="2-9.html">Algorithms</A></P>

<PRE><HR><B><I>Function</I></B><HR></PRE>

<UL>
<LI><A HREF="#sec1">Local Index</A></LI>
<LI><A HREF="#sec2">Summary</A></LI>
<LI><A HREF="#sec3">Synopsis</A></LI>
<LI><A HREF="#sec4">Description</A></LI>
<LI><A HREF="#sec5">Example</A></LI>
<LI><A HREF="#sec6">See Also</A></LI>
<LI><A HREF="#sec7">Standards Conformance</A></LI>
</UL>
<A NAME="sec1"><H3>Local Index</H3></A>
No Entries
<A NAME="sec2"><H3>Summary</H3></A>
<P>Algorithm that returns the maximum of a pair of values</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

<PRE>#include &lt;algorithm&gt;

namespace std {
  template &lt;class T&gt;
  const T&amp; max(const T&amp;, const T&amp;);

  template &lt;class T, class Compare&gt;
  const T&amp; max(const T&amp;, const T&amp;, Compare);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>max()</SAMP> algorithm determines and returns the maximum of a pair of values. In the first case, T must satisfy the requirements of <SAMP>LessThanComparable</SAMP>. In the second case, the optional argument <SAMP>Compare</SAMP> defines a binary function object that can be used in place of the default <SAMP>operator&lt;()</SAMP>.</P>
<P><SAMP>max()</SAMP> returns the first argument when the arguments are equal.</P>
<A NAME="sec5"><H3>Example</H3></A>

<UL><PRE>//
//  max.cpp
//

#include &lt;algorithm&gt;    // for max, min
#include &lt;functional&gt;   // for greater
#include &lt;iostream&gt;     // for cout


int main ()
{
    double d1 = 10.0, d2 = 20.0;

    // Find minimum.
    double val1 = std::min (d1, d2);

    // The greater comparator returns the greater of 
    // the two values.
    double val2 = std::min (d1, d2, std::greater&lt;double&gt;());

    // Find minimum.
    double val3 = std::max (d1, d2);

    // The less comparator returns the smaller of 
    // the two values.

    // Note that, like every comparison in the library, max is
    // defined in terms of the &lt; operator, so using less here
    // is the same as using the max algorithm with a default
    // comparator.
    double val4 = std::max(d1, d2, std::less&lt;double&gt;());

    std::cout &lt;&lt; val1 &lt;&lt; " " &lt;&lt; val2 &lt;&lt; " "
              &lt;&lt; val3 &lt;&lt; " " &lt;&lt; val4 &lt;&lt; std::endl;

    return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>10 20 20 20
</PRE></UL>
<A NAME="sec6"><H3>See Also</H3></A>
<P><SAMP><A HREF="max-element.html">max_element()</A></SAMP>,  <SAMP><A HREF="min.html">min()</A></SAMP>,  <SAMP><A HREF="min-element.html">min_element()</A></SAMP></P>
<A NAME="sec7"><H3>Standards Conformance</H3></A>
<P><I>ISO/IEC 14882:1998 -- International Standard for Information Systems -- Programming Language C++, Sections 25.3.7 and 20.1.2</I></P>

<BR>
<HR>
<A HREF="mask-array.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="max-element.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
