<!--
    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>fill(), fill_n()</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="facets.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.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>fill(), fill_n()</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 assigns the same value to the elements in a given range</P>
<A NAME="sec3"><H3>Synopsis</H3></A>

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

namespace std {
  template &lt;class ForwardIterator, class T&gt;
   void fill(ForwardIterator start, ForwardIterator finish,
             const T&amp; value);

  template &lt;class OutputIterator, class Size, class T&gt;
  void fill_n(OutputIterator start, Size n, const T&amp; value);
}
</PRE>
<A NAME="sec4"><H3>Description</H3></A>
<P>The <SAMP>fill()</SAMP> and <SAMP><A HREF="fill.html">fill_n()</A></SAMP> algorithms are used to assign a value to the elements in a sequence. <SAMP>fill()</SAMP> assigns the value to all the elements designated by iterators in the range <SAMP>[start, finish)</SAMP>.</P>
<P>The <SAMP><A HREF="fill.html">fill_n()</A></SAMP> algorithm assigns the value to all the elements designated by iterators in the range <SAMP>[start, start + n)</SAMP>. <SAMP>fill_n()</SAMP> assumes that all iterators in the range <SAMP>[start, start + n)</SAMP> are dereferenceable, unless <SAMP>start</SAMP> is an insert iterator.</P>
<P>Type <SAMP>T</SAMP> must be Assignable, and <SAMP>Size</SAMP> must be convertible to an integral type.</P>
<A NAME="sec5"><H3>Complexity</H3></A>
<P><SAMP>fill()</SAMP> makes exactly <SAMP>finish - start</SAMP> assignments, and <SAMP><A HREF="fill.html">fill_n()</A></SAMP> makes exactly <SAMP>n</SAMP> assignments.</P>
<A NAME="sec6"><H3>Example</H3></A>

<UL><PRE>//
// fill.cpp
//

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



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

    const vector::value_type arr[] = { 1, 2, 3, 4 };

    // Set up two vectors.
    vector v1(arr, arr + sizeof arr / sizeof *arr);
    vector v2(v1.begin (), v1.end ());

    // Set up one empty vector.
    vector v3;

    // Fill all of v1 with 9.
    std::fill(v1.begin (), v1.end (), 9);

    // Fill first 3 of v2 with 7.
    std::fill_n(v2.begin (), 3, 7);

    // Use insert iterator to fill v3 with 5 11's.
    std::fill_n(std::back_inserter (v3), 5, 11);

    // Copy all three to cout.
    std::ostream_iterator&lt;vector::value_type, char,
             std::char_traits&lt;char&gt; &gt; out(std::cout, " ");

    std::copy(v1.begin (), v1.end (), out);
    std::cout &lt;&lt; std::endl;

    std::copy(v2.begin (), v2.end (), out);
    std::cout &lt;&lt; std::endl;

    std::copy(v3.begin (), v3.end (), out);
    std::cout &lt;&lt; std::endl;

    // Fill cout with 3 5's.
    std::fill_n(out, 3, 5);
    std::cout &lt;&lt; std::endl;

    return 0;
}


Program Output
</PRE></UL>
<UL><PRE>9 9 9 9 
7 7 7 4 
11 11 11 11 11 
5 5 5 
</PRE></UL>
<A NAME="sec7"><H3>See Also</H3></A>
<P><A HREF="algorithms.html">Algorithms</A></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.2.5</I></P>

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