2012-05-30 11 views
10

私はSTLコンテナを印刷するのに役立つネームスペースnsの関数を持っています。たとえば、次のようにboost :: formatとカスタムstdコンテナを印刷する

template <typename T> 
std::ostream& operator<<(std::ostream& stream, const std::set<T>& set) 
{ 
    stream << "{"; 
    bool first = true; 
    for (const T& item : set) 
    { 
     if (!first) 
      stream << ", "; 
     else 
      first = false; 
     stream << item; 
    } 
    stream << "}"; 
    return stream; 
} 

これは直接operator <<で印刷するための素晴らしい作品:

std::set<std::string> x = { "1", "2", "3", "4" }; 
std::cout << x << std::endl; 

はしかし、boost::formatを使用することは不可能です:

std::set<std::string> x = { "1", "2", "3", "4" }; 
boost::format("%1%") % x; 

問題はかなり明白です:ブーストは考えていません私は自分のネームスペースとは何の関係もないタイプをプリントするために私のカスタムoperator <<を使用したいと考えています。 boost/format/feed_args.hppusing宣言を追加する以外に、boost::formatを私のoperator <<にするのに便利な方法はありますか?

+1

私は強くsuggeあなたは基本的にあなたのニーズに答えるので、あなたは[この質問](http://stackoverflow.com/q/4850473/500104)を見てください。あなたの実際の質問が異なるので(私は 'operator <<'について)、私は重複して閉じるよう投票しません。 – Xeo

+2

@ Xeo:私の実際のコードは、どんなコンテナを印刷するのにも非常に似たアプローチを使用しています。とにかく、問題は、 'operator << 'でコンテナを印刷する方法ではなく、Koenigが望んでいないものに対して同じオーバーロード作業を行う方法です。 –

答えて

4

私が考える最もクリーンな方法は、オーバーライドする演算子ごとに独自の名前空間に薄いラッパーを用意することです。あなたのケースでは、それはすることができます。

namespace ns 
{ 
    namespace wrappers 
    { 
     template<class T> 
     struct out 
     { 
      const std::set<T> &set; 

      out(const std::set<T> &set) : set(set) {} 

      friend std::ostream& operator<<(std::ostream& stream, const out &o) 
      { 
       stream << "{"; 
       bool first = true; 
       for (const T& item : o.set) 
       { 
        if (!first) 
         stream << ", "; 
        else 
         first = false; 
        stream << item; 
       } 
       stream << "}"; 
       return stream; 
      } 
     }; 
    } 

    template<class T> 
    wrappers::out<T> out(const std::set<T> &set) 
    { 
     return wrappers::out<T>(set); 
    } 
} 

次に、このようにそれを使用する:私は実際に一緒に行ったソリューションはAnswerorのに非常に似ていますが、それは何のために働く

std::cout << boost::format("%1%") % ns::out(x); 
+0

これは私が実際に使用したソリューションと非常によく似ています。私は私の解決策も掲載しました。 –

1

あなたはこのような何かを試すことができます。

namespace boost // or __gnu_cxx 
{ 
    using np::operator<<; 
} 
#include <boost/format/feed_args.hpp> 
0

としてすでに述べた問題は、ADLである(引数依存の検索 - 多くの場合、アンドリューケーニッヒに起因するが、私は彼がすべての責任を取得するべきではないと考えています) 。

あなたのローカルコンテキストでも、operator<<を使用する予定のテンプレート関数では機能しません。

あなたが定義したoperator<<namespace stdに入れることです。それは動詞ですが、あなたのケースではうまくいくかもしれませんが、その使用前に置かれていれば問題になるかもしれません。

さらに独自のセットテンプレートの定義などのオプションがあります。私は

template<typename T> using Set=std::set<T>; 

で実験が、提供

using np::operator<<; 

yuyoyuppeずに働いたソリューションを得ることができませんでした。

5

namespace ns 
{ 

template <typename T> 
class FormatWrapper 
{ 
public: 
    explicit FormatWrapper(const T& x) : 
      ref(x) 
    { } 

    friend std::ostream& operator<<(std::ostream& stream, 
            const FormatWrapper<T>& self 
            ) 
    { 
     // The key is that operator<< is name lookup occurs inside of `ns`: 
     return stream << self.ref; 
    } 
private: 
    const T& ref; 
}; 

template <typename T> 
FormatWrapper<T> Formatable(const T& x) 
{ 
    return FormatWrapper<T>(x); 
} 

} 

ので使い方は次のとおりです。

boost::format("%1%") % Formatable(x); 
関連する問題