<!--
    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_difference()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="set.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-intersection.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_difference()</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 difference</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_difference(InputIterator1 start1,
                 InputIterator1 finish1,
                 InputIterator2 start2,
                 InputIterator2 finish2,
                 OutputIterator result);
  template &lt;class InputIterator1, class InputIterator2,
            class OutputIterator, class Compare&gt;
  OutputIterator 
  set_difference(InputIterator1 start1,
                 InputIterator1 finish1,
                 InputIterator2 start2,
                 InputIterator2 finish2,
                 OutputIterator result,
                 Compare comp);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>set_difference()</SAMP> algorithm constructs a sorted difference that includes copies of the elements that are present in the range <SAMP>[start1, finish1)</SAMP> but are not present in the range <SAMP>[start2, finish2)</SAMP>. It returns the end of the constructed range. </P>
<P>As an example, assume we have the following two sets:</P>
<P><SAMP>1 2 3 4 5</SAMP></P>
<P>and </P>
<P><SAMP>3 4 5 6 7</SAMP></P>
<P>The result of applying <SAMP>set_difference()</SAMP> is the set:</P>
<P><SAMP>1 2</SAMP></P>
<P>The result of <SAMP>set_difference()</SAMP> is undefined if the result range overlaps with either of the original ranges. </P>
<P><SAMP>set_difference()</SAMP> assumes that the ranges are sorted using <SAMP>operator&lt;()</SAMP>, unless an alternative comparison function object (<SAMP>comp</SAMP>) is provided. </P>
<P>Use the <SAMP>set_symetric_difference()</SAMP> algorithm to obtain a result that contains all elements that are not in common between the two sets.</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_diff.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,2,3,4,5,6,7,8,9,10};
  int a2[6]  = {2,4,6,8,10,12};

  set&lt;int, less&lt;int&gt;,allocator&lt;int&gt; &gt; all(a1+0, a1+10),
                                      even(a2+0, a2+6), odd;

  // Create an insert_iterator for odd.

  insert_iterator&lt;set &lt;int, less&lt;int&gt;,allocator&lt;int&gt; &gt; &gt; 
                 odd_ins(odd, odd.begin());

  // Demonstrate set_difference.

  cout &lt;&lt; "The result of:" &lt;&lt; endl &lt;&lt; "{";
  copy(all.begin(),all.end(),
       ostream_iterator&lt;int,char,char_traits&lt;char&gt; &gt;
                       (cout," "));
  cout &lt;&lt; "} - {";
  copy(even.begin(),even.end(),
       ostream_iterator&lt;int,char,char_traits&lt;char&gt; &gt;
                       (cout," "));
  cout &lt;&lt; "} =" &lt;&lt; endl &lt;&lt; "{";
  set_difference(all.begin(), all.end(), even.begin(),
                 even.end(), odd_ins);
  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; endl;

  return 0;
}


Program Output:
</PRE></UL>
<UL><PRE>The result of:
{1 2 3 4 5 6 7 8 9 10 } - {2 4 6 8 10 12 } =
{1 3 5 7 9 }

</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-intersection.html">set_intersection()</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++, Section 25.3.5.4</I></P>

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