<!--
    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_symmetric_difference()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="set-intersection.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-union.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_symmetric_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 symmetric 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_symmetric_difference(InputIterator1 start1,
                           InputIterator1 finish1,
                           InputIterator2 start2,
                           InputIterator2 finish2,
                           OutputIterator result);
  
  template &lt;class InputIterator1, class InputIterator2,
            class OutputIterator, class Compare&gt;
  OutputIterator
  set_symmetric_difference(InputIterator1 start1,
                           InputIterator1 finish1,
                           InputIterator2 start2,
                           InputIterator2 finish2,
                           OutputIterator result, 
                           Compare comp);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The algorithm <SAMP>set_symmetric_difference()</SAMP> constructs a sorted symmetric difference of the elements from the two ranges. This means that the constructed range includes copies of the elements that are present in the range <SAMP>[start1, finish1)</SAMP> (but not present in the range <SAMP>[start2, finish2)</SAMP>) <I>and</I> copies of the elements that are present in the range <SAMP>[start2, finish2)</SAMP> (but not in the range <SAMP>[start1, finish1)</SAMP>). It returns the end of the constructed range. </P>
<P>For example, suppose we have 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 <SAMP>set_symmetric_difference()</SAMP> of these two sets is:</P>
<P><SAMP>1 2 6 7</SAMP></P>
<P>The result of <SAMP>set_symmetric_difference()</SAMP> is undefined if the result range overlaps with either of the original ranges. </P>
<P><SAMP>set_symmetric_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_symmetric_difference()</SAMP> algorithm to obtain a result that includes elements that are present in the first set and not in the second.</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_s_di.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[] = {1,3,5,7,9,11};
  int a3[] = {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_symmetric_difference.

  cout &lt;&lt; "The symmetric difference 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; "} with {";
  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_symmetric_difference(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 symmetric difference of:
{3 5 7 8 } with {1 3 5 7 9 11 } =
{1 8 9 11 }

</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-difference.html">set_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.5</I></P>

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