Google测试和运营商<< STL类型的重载

时间:2017-04-03 23:23:40

标签: c++ googletest

为什么以下代码会产生编译错误?

#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二进制'&lt;&lt;':找不到右侧的操作符   'const std :: pair'类型的操作数(或者没有可接受的   转换)... \ gtest \ gtest-message.h 131

如何将用户定义的类型更改为内置类型会有所不同?

更新。感谢@Kerrek SB,解释了错误。但是,现在还有另一个问题:我应该如何重载operator&lt;&lt; std::pair能否像我的代码一样使用它?

3 个答案:

答案 0 :(得分: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中的函数替换它,或许更改名称查找?

答案 1 :(得分:2)

当写一个像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);

答案 2 :(得分:0)

您需要在 operator << 命名空间中为 std::pair 定义 std 以便 gtest 找到它。

如下代码编译正常:

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

namespace std
{

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

}

namespace A {

    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; //compiles!
    }
}