<!--
    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>set_intersection()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="set-difference.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="set-symmetric-difference.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>set_intersection()</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>A basic set operation (algorithm) for constructing a sorted intersection</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

namespace std {
  template &lt;class InputIterator1, class InputIterator2, 
            class OutputIterator&gt;
  OutputIterator  
  set_intersection(InputIterator1 start1, 
                   InputIterator1 finish1,
                   InputIterator2 start2, 
                   InputIterator2 finish2,
                   OutputIterator result);
  template &lt;class InputIterator1, class InputIterator2, 
            class OutputIterator, class Compare&gt;
  OutputIterator  
  set_intersection(InputIterator1 start1, 
                   InputIterator1 finish1,
                   InputIterator2 start2, 
                   InputIterator2 finish2, 
                   OutputIterator result, 
                   Compare comp);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>set_intersection()</SAMP> algorithm constructs a sorted intersection of elements from the two ranges. It returns the end of the constructed range. When it finds an element present in both ranges, <SAMP>set_intersection()</SAMP> always copies the element from the first range into <SAMP>result</SAMP>. This means that the result of <SAMP>set_intersection()</SAMP> is guaranteed to be stable.   The result of <SAMP>set_intersection()</SAMP> is undefined if the result range overlaps with either of the original ranges. </P>
<P><SAMP>set_intersection()</SAMP> assumes that the ranges are sorted using <SAMP>operator&lt;()</SAMP>, unless an alternative comparison function object (<SAMP>comp</SAMP>) is provided. </P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P>At most <SAMP>((finish1 - start1) + (finish2 - start2)) * 2 -1</SAMP> comparisons are performed.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
//  set_intr.cpp
//

#include &lt;algorithm&gt;
#include &lt;set&gt;
#include &lt;iostream&gt;

int main ()
{
#ifndef _RWSTD_NO_NAMESPACE
  using namespace std;
#endif


  // Initialize some sets.

  int a1[10] = {1,3,5,7,9,11};
  int a3[4]  = {3,5,7,8};
  set&lt;int, less&lt;int&gt;,allocator&lt;int&gt;  &gt; odd(a1+0, a1+6),
                                       result, 
                                       smalll(a3+0, a3+4);

  // Create an insert_iterator for result.

  insert_iterator&lt;set&lt;int, less&lt;int&gt;,allocator&lt;int&gt; &gt; &gt; 
                  res_ins(result, result.begin());

  // Demonstrate set_intersection.

  cout &lt;&lt; "The result of:" &lt;&lt; endl &lt;&lt; "{";
  copy(smalll.begin(),smalll.end(), 
       ostream_iterator&lt;int,char,char_traits&lt;char&gt; &gt;
                       (cout," "));
  cout &lt;&lt; "} intersection {";
  copy(odd.begin(),odd.end(),
       ostream_iterator&lt;int,char,char_traits&lt;char&gt; &gt;
                       (cout," "));
  cout &lt;&lt; "} =" &lt;&lt; endl &lt;&lt; "{";

  set_intersection(smalll.begin(),smalll.end(),
                   odd.begin(),odd.end(),res_ins);
  copy(result.begin(),result.end(),
       ostream_iterator&lt;int,char,char_traits&lt;char&gt; &gt;
                       (cout," "));
  cout &lt;&lt; "}" &lt;&lt; endl &lt;&lt; endl;

  return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>The result of:
{3 5 7 8 } intersection {1 3 5 7 9 11 } =
{3 5 7 }

</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><SAMP><A HREF="includes.html">includes()</A></SAMP>, <A HREF="iterators.html">Iterators</A>, <SAMP><A HREF="set-union.html">set_union()</A></SAMP>, <SAMP><A HREF="set-difference.html">set_difference()</A></SAMP>, <SAMP><A HREF="set-symmetric-difference.html">set_symmetric_difference()</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++, 25.3.5.3</I></P>

<BR>
<HR>
<A HREF="set-difference.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="set-symmetric-difference.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>
