2017-04-03 75 views
0

爲什麼下面的代碼會產生編譯錯誤?Google測試和運算符<< STL類型的過載

#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 
    } 
} 

我使用Visual Studio 2015年錯誤的文字是:

錯誤C2679二進制「< <」:沒有操作員發現這需要右手 數類型常量性病的」 ::對'(或沒有可接受 轉換)... \ GTEST \ GTEST-message.h 131

如何變化的用戶定義的類型到內置型有差別?

Upd。感謝@Kerrek SB,解釋了錯誤。但是,現在還有另一個問題:我應該如何超載運算符< <的std::pair才能夠像我的代碼一樣使用它?

+0

因爲名稱空間查找不在命名空間'A'中查找您的運算符過載。 –

+0

但是它發現它對'對'。爲什麼它只是沒有找到'對'? –

+1

因爲模板和ADL。 'C'在命名空間'A'中,所以'A'是查找關聯的命名空間。 –

回答

2

我把你的答案,並把它變成一個小例子,在谷歌代碼移除的依賴:

#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<<,這是Google Test包定義的某種類型的宏,而我最簡單的示例將其替換爲名稱空間A中的函數,可能會更改名稱查找?

0

當一個人寫的東西一樣EXPECT_EQ(e1,e2) << some_pair,模板函數

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

被實例化。只有在用戶定義的operator<<這個函數內被調用。由於函數駐留在另一個名稱空間中(不在A中),因此無法找到用戶定義的operator<<

解決方案很簡單。 Gtest提供接受STL容器的功能::testing::PrintToString。所以代碼應該是這樣的(我改變它是有道理的):

EXPECT_TRUE(some_predicate(pair2)) << ::testing::PrintToString(pair2);