2017-04-03 18 views
0

なぜ次のコードでコンパイルエラーが発生するのですか?バイナリGoogleのテストと演算子<< STL型のオーバーロード

エラーC2679 '< <':なしオペレータは型「constのSTDの右 オペランドをとる見つからない::ペア私は、Visual Studio 2015のエラーテキストが使用

#include <iostream> 
#include "gtest/gtest.h" 
#include <utility> 

namespace A { 
    //overloading operator << for std::pair 
    template<typename T1, typename T2> 
    std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) { 
     return os << "pair:{" << p.first << ", " << p.second << "}"; 
    } 

    struct C { 
     int x; 
    }; 
    std::ostream& operator<<(std::ostream& os, const C& c) { 
     return os << c.x; 
    } 

    TEST(TestA, testA) { 
     std::pair<C, C> pair1; 
     std::pair<int, int> pair2; 

     EXPECT_EQ(0, 0) << pair1; //compiles 
     EXPECT_EQ(0, 0) << pair2; //doesn't compile 
    } 
} 

'(あるいは全く許容 変換はありません)... \ GTEST \ GTEST-message.h 131ビルトイン型にユーザー定義型を変更すると違いがどのように

Upd。 @Kerrek SBのおかげで、エラーが説明されています。しかし今、別の質問があります:std::pairのために、私はどのように私のコードのようにそれを使用できるようにオペレータ< <をオーバーロードすべきですか?

+0

:だからコードは、この(私が意味をなすためにそれを変更)のようにする必要があります。 –

+0

しかし、それは 'pair 'のためにそれを見つける。なぜそれは 'pair 'のためにそれを見つけることができないのですか? –

+1

テンプレートとADL。 'C'は名前空間' A'にあるので、 'A'はその検索のための関連する名前空間の中にあります。 –

答えて

2

私はあなたの答えを取り、Googleのコードへの依存を取り除く、最小限の例にそれを回した:

#include <iostream> 

namespace A { 

    template<typename T1, typename T2> 
    std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) { 
     return os << "pair:{" << p.first << ", " << p.second << "}"; 
    } 

    struct C { 
     int x; 
    }; 
    std::ostream& operator<<(std::ostream& os, const C& c) { 
     return os << c.x; 
    } 

    void test() { 
     std::pair<C, C> pair1; 
     std::pair<int, int> pair2; 

     std::cout << pair1 << std::endl; // compiles 
     std::cout << pair2 << std::endl; // also compiles 
    } 
} 

int main(int argc, char *argv[]) { 
    A::test(); 
} 

これは、実際に出力そう

pair:{0, 0} 
pair:{0, 0} 

で、私のために罰金コンパイル、私はあなたの問題を再現できません。しかし、@ KerrekSBはあなたの問題の正当な理由を特定しました。私の違いは、あなたのコードがTEST内でoperator<<を呼び出しているという事実にあると思われます。私の最小限の例ではこれが名前空間Aの関数に置き換えられています。

0

1はEXPECT_EQ(e1,e2) << some_pairのようなもの、

template<typename T> 
::testing::Message::operator<< 

がインスタンス化されているテンプレート関数を書き込みます。この関数内でのみユーザ定義のoperator<<が呼び出されています。関数が別の名前空間(Aではなく)にあるため、ユーザー定義のoperator<<が見つかりません。

解決は簡単です。 GtestはSTLコンテナを受け入れる機能::testing::PrintToStringを提供します。名前の検索があなたの演算子オーバーロードを見つけるために、名前空間 `A`に見ていないので

EXPECT_TRUE(some_predicate(pair2)) << ::testing::PrintToString(pair2); 
関連する問題