汎用的な入出力-----coutの拡張


Coutの拡張
このノートを書くのは完全に1つの問題から始まって、テーマはどのようにiostream反復器でクラスと容器の出力を実現するかです(きっとみんなはとっくにwhileあるいはfor循環を書くことにうんざりしているでしょう、しかもこのように関数をするのは基本的に専用で、共通を実現することはできません).(C++Primer第11章と結合)
最初の試行コードは次のとおりです.

#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using namespace std;

template<class T,classbaseType>

void Show(T &v,baseType r)

{

     //              

     ostream_iterator<baseType>out(cout," ");

      copy(v.begin(),v.end(),out);

     cout<<endl;

}

template<class T>

void Show(T &v)

{

      Show(v,v[0]);               //       ,               

}

int main()

{
     vector<string> vec(10,"Bosch");

     Show(vec,string(""));

     Show(vec);

     return 0;
}

1)        ostream_iteratorout(cout,")は、baseTypeタイプのオブジェクトを出力ストリームcout(ここでは標準出力、または他の出力ストリーム)に書き込むostream反復器を宣言するostream_である.iteratorオブジェクトは、書き込み中にdelimを要素の区切りとして使用します.Delimは空の文字で終わる文字配列です.
2)copy(v.begin()、v.end()、out)は、タイプTの反復器対範囲内の要素をout反復出力ストリームにコピーする.
3)この関数は、任意の1次元コンテナを出力する機能を実現します(もちろん、コンテナにはベースタイプを格納する必要があります).
 
1 D出力に成功した後、2 Dコンテナを試してみましたが、あまり理想的ではなく、コンパイル期間中に一致が見つからないような「<」オペレータのエラーが報告されます.まずプログラムを見てください.

#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;


template<class T,class baseType>

void Show(T &v,baseType r)

{
      ostream_iterator<baseType> out(cout," ");

      copy(v.begin(),v.end(),out);

      cout<<endl;

}

 
template<class T>

void Show(T &v)

{

       Show(v,v[0]);

}

 
int main()

{

       vector<string> vec(10,"Bosch");

       Show(vec,string(""));

       Show(vec);

      
       vector<vector<string> > dvec(2,vec);

       Show(dvec[0],string(""));

       Show(*dvec.begin(),string(""));

      
       Show(dvec,vec);

       ostream_iterator< vector<string> > out(cout," ");

       copy(dvec.begin(),dvec.end(),out);

 

}

Show(dvec,vec);
copy(dvec.begin(),dvec.end(),out);
上の2つの言葉のコンパイルが通らないし、大きな間違いが出てきて、本当に無言で、私は理解できません.後に経験のあるプログラマーの高人さんは、「<<「マッチングが見つからない.
 

#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;

ostream& operator << (ostream& os,vector<string>&vec)

{

       vector<string>::iterator iter = vec.begin();

       while (iter != vec.end())

       {

             os<<*iter++<<" 0 ";

       }

      os<<endl;

 

      return os;

}
 
template<class T,class baseType>

void Show(T &v,baseType r)

{

        ostream_iterator<baseType> out(cout," ");

        copy(v.begin(),v.end(),out);

        cout<<endl;

}

 
template<class T>

void Show(T &v)

{

       Show(v,v[0]);

}


int main()

{

       vector<string> vec(10,"Bosch");

       Show(vec,string(""));

       Show(vec);

       cout<<vec;

       vector<vector<string> > dvec(2,vec);

       Show(dvec[0],string(""));

       Show(*dvec.begin(),string(""));

       ostream_iterator< vector<string> > out(cout," ");              


       copy(dvec.begin(),dvec.end(),out);

       Show(dvec,vec);
}

       copy(dvec.begin(),dvec.end(),out);
       Show(dvec,vec);
この2行はまだコンパイルが通らず、エラーが同じなのか、一致する「<」オペレータが見つからないのか、私は本当に憂鬱です.今はcopyの内部に問題があるだけで、stackoverflowのウェブサイトでコードを見つけました.

template<class InputIterator, class OutputIterator>

OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)

{

      while (first != last) *result++ = *first++;

      return result;

}

 
見終わって少し驚いて、copy関数は意外にもこんなに簡単で、私達は本当に標準ライブラリを見るのがあまり難しくないようですが、しかしこのような簡単な1行のコード、どうして、私はvectorが賦値操作を支持しないことを推測するしかなくて、結果の簡単なテストはすぐにこの仮説を覆しました.
これで窮屈になったので、無理にostreamを探すことはできません.iteratorの実装、myostreamと命名iterator(名前を変更しないと再定義されます):

template <class T, class charT=char, class traits=char_traits<charT> >

class myostream_iterator :public iterator<output_iterator_tag, void, void, void, void>

{

  basic_ostream<charT,traits>* out_stream;

  const charT* delim;

 

public:

  typedef charT char_type;

  typedef traits traits_type;

  typedef basic_ostream<charT,traits> ostream_type;

 

  myostream_iterator(ostream_type& s) : out_stream(&s), delim(0) {}

  myostream_iterator(ostream_type& s, const charT* delimiter)

    : out_stream(&s), delim(delimiter) { }

  myostream_iterator(const myostream_iterator<T,charT,traits>& x)

    : out_stream(x.out_stream), delim(x.delim) {}

  ~myostream_iterator() {}

 

  //    ,  “<<“        。

  myostream_iterator<T,charT,traits>& operator= (const T& value) {

    *out_stream << value;

    if (delim!=0) *out_stream << delim;

    return *this;

  }

 

 

  myostream_iterator<T,charT,traits>& operator*() { return *this; }

  myostream_iterator<T,charT,traits>& operator++() { return *this; }

  myostream_iterator<T,charT,traits>& operator++(int) { return *this; }

};

 
辛抱強く研究してみると、このクラスは複雑ではありません.比較的下位のbasicを除いて.ostreamタイプはあまり見たことがないので、他は分かりやすいです.エラーを発見するのは難しくありません:myostream_iterator&operator=(constT&value)の*out_stream << value;この言葉は、重荷重が必要なのですが、なぜ重荷重が使いにくいのか、私はまた重荷重の別のバージョンを試してみました.

typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,vector<string>& vec)

 {

            vector<string>::iterator iter = vec.begin();

            while (iter != vec.end())

            {

                        os<<(*iter++)<<" ";

            }

            os<<endl;

            return os;

 }

この関数をクラスに配置し始めたが、結果は使いにくく、関数呼び出しのパラメータが1つ少ないことを示した(どのように改善するかはまだ分からない)後、この関数を外に置いたが、結果は依然としてエラーだった.結果は次のように発見された.
 myostream_iterator&operator= (const T& value)
 
の2番目のパラメータは定数タイプなので、リロード関数もconstタイプの参照パラメータでなければなりません.そうしないと一致せず、呼び出されません.
 
注意:C++では、関数を再ロードすると、コンパイラは通常参照パラメータと非常参照パラメータを認識するため、異なる関数バージョンが発生し、この特性を無視すると隠れたエラーが発生します.非常に参照されているパラメータは、定数参照を実パラメータとして受け入れないからです.
 
上記の事実も、リロード後も無効な錯覚であり、改善後もコンパイルが通過しないことが分かった.
vector::iterator iter = vec.begin();
この文の理由は、定数反復器を宣言する必要があります.修正されたコードは次のとおりです.

typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)

  {

        vector<string>::const_iterator iter = vec.begin();

        while (iter != vec.end())

        {

             os<<(*iter++)<<" ";

        }

        os<<endl;

        return os;

  }

 
これで、必要な2 Dコンテナも正常に出力できます.最終コードは次のとおりです.

#include<iostream>

#include<fstream>

#include<vector>

#include<algorithm>

#include<iterator>

#include<string>

using  namespace std;

typedef basic_ostream<char,char_traits<char> >  ostream_Type;

///you can see the ostream_Type as ostream.

 

ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)

{

     vector<string>::const_iterator iter = vec.begin();

     while (iter != vec.end())

     {

          os<<(*iter++)<<" ";

     }

     os<<endl;

     return os;

}
 

template <class T, class charT=char, class traits=char_traits<charT> >

class myostream_iterator :public iterator<output_iterator_tag, void, void, void, void>

{

  basic_ostream<charT,traits>* out_stream;

  //ostream* out_stream;

  const charT* delim;

public:

  typedef charT char_type;

  typedef traits traits_type;

  typedef basic_ostream<charT,traits> ostream_type;

  //typedef ostream ostream_type;

  myostream_iterator(ostream_type& s) : out_stream(&s), delim(0) {}

  myostream_iterator(ostream_type& s, const charT* delimiter)

    : out_stream(&s), delim(delimiter) { }

  myostream_iterator(const myostream_iterator<T,charT,traits>& x)

    : out_stream(x.out_stream), delim(x.delim) {}

  ~myostream_iterator() {}

 

  myostream_iterator<T,charT,traits>& operator= (const T& value) {

    *out_stream << value;

    if (delim!=0) *out_stream << delim;

    return *this;

  }

 

  myostream_iterator<T,charT,traits>& operator*() { return *this; }

  myostream_iterator<T,charT,traits>& operator++() { return *this; }

  myostream_iterator<T,charT,traits>& operator++(int) { return *this; }

};

 
template<class T,class baseType>

void Show(T &v,baseType r)

{

     myostream_iterator<baseType> out(cout," ");

     copy(v.begin(),v.end(),out);

     cout<<endl;

}


/*ostream& operator << (ostream& os,const vector<string>&vec)

{

   vector<string>::const_iterator iter = vec.begin();

     while (iter != vec.end())

     {

          os<<*iter++<<" 0 ";

     }

     os<<endl;

     return os;

}*/

 
template<class InputIterator, class OutputIterator>

OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)

{

   while (first != last) *result++ = *first++;

   return result;

}

 
template<class T>

void Show(T &v)

{
     Show(v,v[0]);
}

int main()

{

     vector<string> vec(10,"Bosch");

     Show(vec);

     Show(vec,string(""));

     cout<<vec;

     vector<vector<string> > dvec(2,vec);

     Show(dvec[0],string(""));

     Show(*dvec.begin(),string(""));

     myostream_iterator< vector<string> > out(cout," ");

     vector<string> tes = vec;

     //*out<<*dvec.begin();

     mycopy(dvec.begin(),dvec.end(),out);


     cout<<"*******************Success*********************"<<endl;

     Show(dvec,vec);
}

 
ostream& operator << (ostream& os,const vector&vec)
ostream_Type& operator << (ostream_Type& os,constvector& vec)
両方のバージョンはこのプログラムで使用できます.加重された部分はほぼ等価で、差は後で探ってみましょう.
 
上は私たち自身のコードを使用しています.下はcoutを再ロードする以外はライブラリ関数を完全に使用します.つまり、ライブラリのostream_を使用します.iteratorは依然として间违って、无言で、何度も试して私は依然として手の施しようがなくて、それでは仕方がなくて、linuxの下で标准的なライブラリのソースコードを见て、结局ネット上で探したostream_iteratorソースコードは権威が足りないかもしれません.
度娘は本当にいいもので、検索してiostreamを知った.iteratorはヘッダファイルに含まれ、/usr/include/c++の下に入ってヘッダファイルを見つけ、開くと次のようになります.
 
直接定義は得られませんが、少し観察するとstream_があります.iterator.hでは、このファイルで開くファイルは本当にあると推測できます(ここにはostream_iteratorコードしか貼られていません.その他の完全なコードはブログのソースディレクトリの下に参照してください):

/**

   *  @brief  Provides output iterator semantics for streams.

   *

   *  This class provides an iterator to write to an ostream.  The type Tp is

   *  the only type written by this iterator and there must be an

   *  operator<<(Tp) defined.

   *

   *  @param  Tp  The type to write to the ostream.

   *  @param  CharT  The ostream char_type.

   *  @param  Traits  The ostream char_traits.

  */

  template<typename _Tp, typename _CharT = char,

           typename _Traits = char_traits<_CharT> >

    class ostream_iterator

    : public iterator<output_iterator_tag, void, void, void, void>

    {

    public:

      //@{

      /// Public typedef

      typedef _CharT                         char_type;

      typedef _Traits                        traits_type;

      typedef basic_ostream<_CharT, _Traits> ostream_type;

      //@}

 

    private:

      ostream_type*   _M_stream;

      const _CharT*   _M_string;

 

    public:

      /// Construct from an ostream.

      ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}

 

      /**

       *  Construct from an ostream.

       *

       *  The delimiter string @a c is written to the stream after every Tp

       *  written to the stream.  The delimiter is not copied, and thus must

       *  not be destroyed while this iterator is in use.

       *

       *  @param  s  Underlying ostream to write to.

       *  @param  c  CharT delimiter string to insert.

      */

      ostream_iterator(ostream_type& __s, const _CharT* __c)

      : _M_stream(&__s), _M_string(__c)  { }

 

      /// Copy constructor.

      ostream_iterator(const ostream_iterator& __obj)

      : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }

 

      /// Writes @a value to underlying ostream using operator<<.  If

      /// constructed with delimiter string, writes delimiter to ostream.

      ostream_iterator&

      operator=(const _Tp& __value)

      {

    __glibcxx_requires_cond(_M_stream != 0,

                 _M_message(__gnu_debug::__msg_output_ostream)

                 ._M_iterator(*this));

    *_M_stream << __value;

    if (_M_string) *_M_stream << _M_string;

    return *this;

      }

 
      ostream_iterator&

      operator*()

      { return *this; }

 
      ostream_iterator&

      operator++()

      { return *this; }

 
      ostream_iterator&

      operator++(int)

      { return *this; }

    };

 
ソースコードを見終わったら、もっと困惑しました.なぜ、このバージョンは私たちの上のバージョンとほとんど同じなのか、標準ostream_iterator置換上のmyostream_iterator(もちろんこの場合を含める必要はありません)、結果は予想外で、結果はすべて正常です.よく探してみると、標準ライブラリでリロードした関数が見つからないかもしれません.すぐに、上のライブラリファイルstream_iteratorはiostreamという名前のコピーをします.iterator.h現在の作業ディレクトリに配置し、includeは含み、予想外にエラーが報告され、リロードされた「<<」関数をヘッダファイルに入れてコンパイルしました.これで私たちは問題の根源を見つけた.
最終ソース:
(1)iostream_iterator.h

// Stream iterators

// Copyright (C) 2001, 2004, 2005, 2009 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file stream_iterator.h
 *  This is an internal header file, included by other library headers.
 *  You should not attempt to use it directly.
 */

#ifndef _STREAM_ITERATOR_H
#define _STREAM_ITERATOR_H 1

#pragma GCC system_header

#include <debug/debug.h>

_GLIBCXX_BEGIN_NAMESPACE(std)

  /// Provides input iterator semantics for streams.
  template<typename _Tp, typename _CharT = char,
           typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t>
    class istream_iterator
    : public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&>
    {
    public:
      typedef _CharT                         char_type;
      typedef _Traits                        traits_type;
      typedef basic_istream<_CharT, _Traits> istream_type;

    private:
      istream_type*    _M_stream;
      _Tp        _M_value;
      bool        _M_ok;

    public:
      ///  Construct end of input stream iterator.
      istream_iterator()
      : _M_stream(0), _M_value(), _M_ok(false) {}

      ///  Construct start of input stream iterator.
      istream_iterator(istream_type& __s)
      : _M_stream(&__s)
      { _M_read(); }

      istream_iterator(const istream_iterator& __obj)
      : _M_stream(__obj._M_stream), _M_value(__obj._M_value),
        _M_ok(__obj._M_ok)
      { }

      const _Tp&
      operator*() const
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_deref_istream)
                ._M_iterator(*this));
    return _M_value;
      }

      const _Tp*
      operator->() const { return &(operator*()); }

      istream_iterator&
      operator++()
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_inc_istream)
                ._M_iterator(*this));
    _M_read();
    return *this;
      }

      istream_iterator
      operator++(int)
      {
    __glibcxx_requires_cond(_M_ok,
                _M_message(__gnu_debug::__msg_inc_istream)
                ._M_iterator(*this));
    istream_iterator __tmp = *this;
    _M_read();
    return __tmp;
      }

      bool
      _M_equal(const istream_iterator& __x) const
      { return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream); }

    private:
      void
      _M_read()
      {
    _M_ok = (_M_stream && *_M_stream) ? true : false;
    if (_M_ok)
      {
        *_M_stream >> _M_value;
        _M_ok = *_M_stream ? true : false;
      }
      }
    };

  ///  Return true if x and y are both end or not end, or x and y are the same.
  template<typename _Tp, typename _CharT, typename _Traits, typename _Dist>
    inline bool
    operator==(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y)
    { return __x._M_equal(__y); }

  ///  Return false if x and y are both end or not end, or x and y are the same.
  template <class _Tp, class _CharT, class _Traits, class _Dist>
    inline bool
    operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,
           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y)
    { return !__x._M_equal(__y); }

  /**
   *  @brief  Provides output iterator semantics for streams.
   *
   *  This class provides an iterator to write to an ostream.  The type Tp is
   *  the only type written by this iterator and there must be an
   *  operator<<(Tp) defined.
   *
   *  @param  Tp  The type to write to the ostream.
   *  @param  CharT  The ostream char_type.
   *  @param  Traits  The ostream char_traits.
  */
  template<typename _Tp, typename _CharT = char,
           typename _Traits = char_traits<_CharT> >
    class ostream_iterator
    : public iterator<output_iterator_tag, void, void, void, void>
    {
    public:
      //@{
      /// Public typedef
      typedef _CharT                         char_type;
      typedef _Traits                        traits_type;
      typedef basic_ostream<_CharT, _Traits> ostream_type;
      //@}

    private:
      ostream_type*    _M_stream;
      const _CharT*    _M_string;

    public:
      /// Construct from an ostream.
      ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}

      /**
       *  Construct from an ostream.
       *
       *  The delimiter string @a c is written to the stream after every Tp
       *  written to the stream.  The delimiter is not copied, and thus must
       *  not be destroyed while this iterator is in use.
       *
       *  @param  s  Underlying ostream to write to.
       *  @param  c  CharT delimiter string to insert.
      */
      ostream_iterator(ostream_type& __s, const _CharT* __c)
      : _M_stream(&__s), _M_string(__c)  { }

      /// Copy constructor.
      ostream_iterator(const ostream_iterator& __obj)
      : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }

      /// Writes @a value to underlying ostream using operator<<.  If
      /// constructed with delimiter string, writes delimiter to ostream.
      ostream_iterator&
      operator=(const _Tp& __value)
      {
    __glibcxx_requires_cond(_M_stream != 0,
                _M_message(__gnu_debug::__msg_output_ostream)
                ._M_iterator(*this));
    *_M_stream << __value;
    if (_M_string) *_M_stream << _M_string;
    return *this;
      }

      ostream_iterator&
      operator*()
      { return *this; }

      ostream_iterator&
      operator++()
      { return *this; }

      ostream_iterator&
      operator++(int)
      { return *this; }
    };
    
    
typedef basic_ostream<char,char_traits<char> >  ostream_Type;    
ostream_Type& operator << (ostream_Type& os,const vector<string>& vec)
{
    vector<string>::const_iterator iter = vec.begin();
    while (iter != vec.end())
    {
        os<<(*iter++)<<" ";
    }
    os<<endl;
    return os;
}
 
ostream_Type& operator << (ostream_Type& os,vector<string>& vec)
{
    vector<string>::iterator iter = vec.begin();
    while (iter != vec.end())
    {
        os<<(*iter++)<<" ";
    }
    os<<endl;
    return os;
}

_GLIBCXX_END_NAMESPACE

#endif

 (1)main.c
#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
#include<string>
#include"iostream_iterator.h"
using  namespace std;
//typedef basic_ostream<char,char_traits<char> >  ostream_Type;
///you can see the ostream_Type as ostream.


template<class T,class baseType>
void Show(T &v,baseType r)
{
	ostream_iterator<baseType> out(cout," ");
	copy(v.begin(),v.end(),out);
	cout<<endl;
}


/*ostream& operator << (ostream& os,const vector<string>&vec)
{
   vector<string>::const_iterator iter = vec.begin();
	while (iter != vec.end())
	{
		os<<*iter++<<" 0 ";
	}
	os<<endl;
	return os;
}*/

template<class InputIterator, class OutputIterator>
OutputIterator mycopy (InputIterator first, InputIterator last, OutputIterator result)
{
   while (first != last) *result++ = *first++;
   return result;
}

template<class T>
void Show(T &v)
{
	Show(v,v[0]);
}


int main()
{
	vector<string> vec(10,"Bosch");
	Show(vec);
	Show(vec,string(""));
	cout<<vec;
	vector<vector<string> > dvec(2,vec);
	Show(dvec[0],string(""));
	Show(*dvec.begin(),string(""));
	ostream_iterator< vector<string> > out(cout," ");
	vector<string> tes = vec;
	//*out<<*dvec.begin();
	copy(dvec.begin(),dvec.end(),out);
	
	cout<<"*******************Success*********************"<<endl;
	Show(dvec,vec);
}

この問題を解決したにもかかわらず、コードをmainに直接貼り付けると考えるべき問題が出てきた.cの場合、重荷の「<<」を見つけることができるのですが、なぜincludeはできないのでしょうか.以前はincludeの動作を「写し」と理解していたのではないでしょうか.
忍耐強いテストにより、includeに対する理解の誤りではなく、ネーミングスペースの問題、iostream_iterator.hで使用するネーミングスペースは、私たちのプライマリファイルとは異なるので、関数が見つかりません.iostream_iterator.h前にusing namespace stdを1本追加する.問題は円満に解決された.
ネーミングスペースは検討に値するもののようですが、よく研究する必要があります.
CSDN高人の指摘:
これはc++名前検索ルールによるものです.カスタムoperator<(xxx,vectorを提供する暗黙型変換クラスvector_wrapperであり、operator<(xxx,vector_wrapper)(Koenig名前検索)を提供しない
したがって、現在の理想的な解決策は、stdにリロードされた「<<」を入れることである.
namespace std{

ostream& operator << (ostream& os,const vector<string>&vec)
{
   vector<string>::const_iterator iter = vec.begin();
	while (iter != vec.end())
	{
		os<<*iter++<<" 0 ";
	}
	os<<endl;
	return os;
}

}

 
参照先:
http://bytes.com/topic/c/answers/716006-ostream_iterator-vector-pair-int-string http://www.cnblogs.com/zhenjing/archive/2010/10/20/1856309.html