2017-04-03 70 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);