4

stl コンテナーを ostream に書き込みたいことがよくあります。次のコードは正常に機能します (少なくともベクターとリストの場合)。

template< typename T ,template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container >
std::ostream& operator<< (std::ostream& o, Container<T>const & container){
  typename Container<T>::const_iterator beg = container.begin();
  while(beg != container.end()){
    o << *beg++;
    if (beg!=container.end())  o << "\t";
  }
  return o;
}

ここで、このコードを拡張して、カスタマイズ可能なセパレーターをサポートしたいと考えています。次のアプローチは明らかに機能しません。これは、オペレーターが 2 つのパラメーターのみを受け取ることになっているためです。

template< typename T ,template<typename ELEM, typename ALLOC=std::allocator<ELEM> > class Container >
std::ostream& operator<< (std::ostream& o, Container<T>const & container,char* separator){
  typename Container<T>::const_iterator beg = container.begin();
  while(beg != container.end()){
    o << *beg++;
    if (beg!=container.end())  o << separator;
  }
  return o;
}

シングルトンやグローバル変数に頼らずに、このようなことを達成できますか?

理想的なのは、カスタム フラグまたは などのストリーム マニピュレータを導入することstd::fixedです。その後、次のように書くことができます

std::cout << streamflags::tabbed << myContainer;
4

2 に答える 2

4

独自のマニピュレータを作成できます。関数ポインターを取り(リンクの (9) を参照)、ストリーム自体をパラメーターとして渡してその関数を呼び出すオーバーロードをbasic_ostream提供します。したがって、マニピュレータは単なる関数名です。operator<<

あるいは、マニピュレータは、適切な を持つオブジェクトにすることもできますoperator<<。これにより、次のように書くことができますcout << setSeparator(',') << myContainer;。ここでsetSeparatorは、コンストラクタを持つクラスsetSeparator(char)です。

最後に、基本的に任意の情報を特定のストリーム インスタンスに関連付けることができる、およびメンバーをios_base提供します。これが、マニピュレータが と通信する方法です。によって割り当てられたインデックスを格納するには、1 つのグローバル変数が必要です。xallociwordpwordoperator<<(Container)xalloc

于 2013-08-08T18:44:10.413 に答える