<!--
    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>find_first_of()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="find-end.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="find-if.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>find_first_of()</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">Complexity</A></LI>
<LI><A HREF="#sec6">Example</A></LI>
<LI><A HREF="#sec7">See Also</A></LI>
<LI><A HREF="#sec8">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 finds the first occurrence of any value from one sequence in another sequence</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

namespace std {
  template &lt;class ForwardIterator1, class ForwardIterator2&gt;
  ForwardIterator1 find_first_of (ForwardIterator1 start1,
                                  ForwardIterator1 finish1,
                                  ForwardIterator2 start2,
                                  ForwardIterator2 finish2);

  template &lt;class ForwardIterator1, class ForwardIterator2,
            class BinaryPredicate&gt;
  ForwardIterator1 find_first_of (ForwardIterator1 start1,
                                  ForwardIterator1 finish1,
                                  ForwardIterator2 start2,
                                  ForwardIterator2 finish2,
                                  BinaryPredicate binary_pred);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>find_first_of()</SAMP> algorithm finds the first occurrence of a value from a sequence, specified by <SAMP>start2, finish2</SAMP>, in a sequence specified by <SAMP>start1, finish1</SAMP>. The algorithm returns an iterator in the range <SAMP>[start1, finish1) </SAMP>that points to the first matching element<SAMP>.</SAMP> If the first sequence <SAMP>[start1, finish1)</SAMP> does not contain any of the values in the second sequence, <SAMP>find_first_of()</SAMP> returns <SAMP>finish1</SAMP>. </P>
<P>In other words, <SAMP>find_first_of()</SAMP> returns the first iterator <SAMP>i</SAMP> in <SAMP>[start1, finish1)</SAMP>such that for some iterator <SAMP>j</SAMP> in the range <SAMP>[start2, finish2)</SAMP>, the following conditions hold: </P>

<UL><PRE>*i == *j, binary_pred(*i,*j) == true.
</PRE></UL>
<P>Or <SAMP>find_first_of()</SAMP> returns <SAMP>finish1</SAMP> if no such iterator is found.</P>
<P>Two versions of the algorithm exist. The first uses the equality operator as the default binary predicate, and the second allows you to specify a binary predicate.</P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>At most <SAMP>(finish1 - start1)*(finish2 - start2)</SAMP> applications of the corresponding predicate are done.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
// find_f_o.cpp
//

#include &lt;algorithm&gt;    // for find_first_of
#include &lt;functional&gt;   // for equal_to
#include &lt;iostream&gt;     // for cout, endl
#include &lt;vector&gt;       // for vector


int main ()
{
    // Typedef for convenience.
    typedef std::vector&lt;int, std::allocator&lt;int&gt; &gt; vector;

    const vector::value_type a1[] = { 
        0, 1, 2, 2, 3, 4, 2, 2, 6, 7 
    };
    const vector::value_type a2[] = { 6, 4 };

    // Set up two vectors.
    const vector v1(a1, a1 + sizeof a1 / sizeof *a1);
    const vector v2(a2, a2 + sizeof a2 / sizeof *a2);

    // Try both find_first_of variants.
    vector::const_iterator it1 =
        std::find_first_of(v1.begin(), v1.end(), 
                           v2.begin(), v2.end()); 

    vector::const_iterator it2 =
        std::find_first_of(v1.begin(), v1.end(), 
                           v2.begin(), v2.end(),
                        std::equal_to&lt;vector::value_type&gt;());

    // Create an output stream iterator.
    std::ostream_iterator&lt;vector::value_type, char,
        std::char_traits&lt;char&gt; &gt; out(std::cout, " " );

    // Output results.
    std::cout &lt;&lt; "For the vectors { ";
    std::copy(v1.begin(), v1.end(), out);

    std:: cout &lt;&lt; "} and { ";
    std::copy(v2.begin(), v2.end(), out);

    std::cout &lt;&lt; "}\nboth versions of find_first_of "
              &lt;&lt; "point to: " &lt;&lt; *it1 &lt;&lt; std::endl; 

    // Return 0 on success, non-0 on failure.
    return !(*it1 == *it2);
}


Program Output
</PRE></UL>
<UL><PRE>For the vectors { 0 1 2 2 3 4 2 2 6 7 } and { 6 4 }
both versions of find_first_of point to: 4
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><A HREF="algorithms.html">Algorithms</A>, <SAMP><A HREF="adjacent-find.html">adjacent_find()</A></SAMP>, <SAMP><A HREF="find.html">find()</A></SAMP>, <SAMP><A HREF="find-if.html">find_if()</A></SAMP>, <SAMP><A HREF="find-end.html">find_end()</A></SAMP></P>
<A NAME="sec8"><H3>Standards Conformance</H3></A>
<P><I>ISO/IEC 14882:1998 -- International Standard for Information Systems -- Programming Language C++, Section 25.1.4</I></P>

<BR>
<HR>
<A HREF="find-end.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="find-if.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>
