2013-10-26 7 views
10

オーバーロードによるオーバーヘッドによるループベースのサポートを備えたすべてのクラスに対して、きれいな印刷を実装したい< <。 (間違った)コードはこのようなものです。ループベースの汎用サポートを持つすべてのクラスの印刷物

template<class C> ostream& operator<<(ostream& out, const C& v) { 
    for(auto x : v) out<<x<<' '; 
    return out; 
} 

ここでの問題は、これが既存の< <オーバーロードと競合するということです。テンプレートで、Cがranged-base forループをサポートしなければならないことを指定する方法はありますか?

答えて

11

範囲ベースのforループは、ADL(とstd::が関連付けられた名前空間である)で有効であることがbegin(v)end(v)を必要とするため、あなたはこの使用することができます。

namespace support_begin_end 
{ 
    // we use a special namespace (above) to 
    // contain the using directive for 'std': 
    using namespace std; 

    // the second parameter is only valid 
    // when begin(C()) and end(C()) are valid 
    template<typename C, 
     typename=decltype(begin(std::declval<C>()),end(std::declval<C>())) 
    > 
    struct impl 
    { 
     using type = void; // only here impl 
    }; 

    // explicitly disable conflicting types here 
    template<> 
    struct impl<std::string>; 
} 

// this uses the above to check for ::type, 
// which only exists if begin/end are valid 
// and there is no specialization to disable it 
// (like in the std::string case) 
template<class C,typename = typename supports_begin_end::impl<C>::type> 
std::ostream& operator<<(std::ostream& out, const C& v) { 
    for(auto x : v) out<<x<<' '; 
    return out; 
} 

Live example

を、他の種類があります。ただし、範囲ベースのループに適しています。あなたもそれらを検出する必要があるかどうかわからない。


は、ここでコンテナ/ begin(v)/end(v)をサポートするタイプだけでなく、v.begin()/v.end()をサポートするタイプの両方を検出し、更新live exampleです。

+0

ここで何が起こっているのか少し説明していただけますか?素敵なおかげです! – lfxgroove

+0

@lfxgroove更新された回答が役立つかどうかを確認してください。 –

+0

確かに、ヒープありがとう! – lfxgroove

6

SFINAE:

template<class C> 
auto operator<<(std::ostream& out, const C& v) -> decltype(v.begin(), v.end(), (out)) 
//           or -> decltype(std::begin(v), std::end(v), (out)) 
{ 
    for (auto x : v) 
     out << x << ' '; 
    return out; 
} 
4

すべての答えの一般的なコメント:

for (auto x : v) 

を使用したが、たくさんで、その結果、それらを印刷する前に、コレクションのうち、すべての要素をコピーしますコピーコンストラクタとデストラクタへの呼び出し

for (auto &x : v) 

をループとして使用する方がよいでしょう。