【问题标题】:How to get a custom operator== to work with Google Test?如何让自定义 operator== 与 Google Test 一起使用?
【发布时间】:2015-10-27 14:47:51
【问题描述】:

我在使用带有 PCL 和 Google 测试 (GTest) 的自定义重载“==”运算符时遇到问题

#include <pcl/point_types.h>
namespace pcl { struct PointXYZ; }

bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
#include <gtest/gtest.h>

TEST(Foo, bar) {
  pcl::PointXYZ a{2,3,4};
  pcl::PointXYZP b{2,3,4};
  EXPECT_EQ(a,b); // Compile error no match for operator==
}

int main(int argc, char **argv){
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

我得到的错误是:

|| /usr/include/gtest/gtest.h: In instantiation of 'testing::AssertionResult testing::internal::CmpHelperEQ(const char*, const char*, const T1&, const T2&) [with T1 = pcl::PointXYZ; T2 = pcl::PointXYZ]':
/usr/include/gtest/gtest.h|1361 col 23| required from 'static testing::AssertionResult testing::internal::EqHelper<lhs_is_null_literal>::Compare(const char*, const char*, const T1&, const T2&) [with T1 = pcl::PointXYZ; T2 = pcl::PointXYZ; bool lhs_is_null_literal = false]'
src/foo/src/tests.cpp|20 col 3| required from here
/usr/include/gtest/gtest.h|1325 col 16| error: no match for 'operator==' (operand types are 'const pcl::PointXYZ' and 'const pcl::PointXYZ')
||    if (expected == actual) {
||                 ^
/usr/include/gtest/internal/gtest-linked_ptr.h|213 col 6| note: candidate: template<class T> bool testing::internal::operator==(T*, const testing::internal::linked_ptr<T>&)
||  bool operator==(T* ptr, const linked_ptr<T>& x) {
||       ^
/usr/include/gtest/internal/gtest-linked_ptr.h|213 col 6| note:   template argument deduction/substitution failed:
/usr/include/gtest/gtest.h|1325 col 16| note:   mismatched types 'T*' and 'pcl::PointXYZ'

我试图坚持底漆: https://github.com/google/googletest/blob/master/googletest/docs/primer.md#binary-comparison

特别是,我的运算符是在包含 gtest 之前定义的,我确信类型匹配。我还尝试编写重载以获取 const 引用,但这只是比较地址而不是值。

【问题讨论】:

  • 尝试将operator == 移动到与PointXYZ 相同的命名空间中。
  • 错误表示它正在尝试比较const pcl::PointXYZs。如果您将operator== 更改为bool operator==(const pcl::PointXYZ&amp; p1, const pcl::PointXYZ&amp; p2) {return p1.x-p2.x&lt;.1;},会发生什么?

标签: c++ operator-overloading googletest


【解决方案1】:

自定义类型的运算符是通过参数相关查找找到的。

依赖于参数的查找(简而言之)意味着函数可以被视为如果它们被定义在同一命名空间中作为它们的一个或多个参数。

这段代码:

namespace pcl { struct PointXYZ; }

bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}

pcl:: 命名空间中定义PointXYZ,但在全局命名空间中定义operator== 函数。因此,不是 ADL 的候选人。

这样做:

namespace pcl { 
  struct PointXYZ; 
  bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
}

修复了这个问题,因为现在 operator== 的名称为 pcl::operator==,它与其参数之一位于相同的命名空间中(实际上在这种情况下它们都是,但你明白了)。这使它成为 ADL 期间的候选者,因此它将在 gtest 调用相等测试时被选中。

【讨论】:

  • 谢谢;这是我理解命名空间如何工作的一个巨大漏洞。具有兼容参数的全局命名空间中的函数不是候选函数是违反直觉的,但我认为它更符合类如何进行命名空间。我想知道如果/当 C++ 获得 UFCS 时,像这样直观但无效的代码是否会开始工作。
  • 不久你就会开始发现它的做法是合理的。它将运算符和它们相关的对象放在一起。此外,它还防止了全局命名空间的污染,这会导致极难定位的细微错误。
  • @Ankur 是的。您将定义 operator== 以将参数作为 const 引用。
  • @RichardHodges 我也遇到了类似的问题,但发现 EXPECT_TRUE 在这种情况下有效,而不是 EXPECT_EQ,对此有什么想法吗?
  • @Tejendra EXPECT_TRUE 要求隐式或显式转换为 bool(或任何数字类型)
【解决方案2】:

namespace pcl 中包含operator== 定义:

#include <pcl/point_types.h>
namespace pcl
{
    bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
}

此外,您可以删除 pcl::PointXYZ 的前向声明,因为它必须在标头 pcl/point_types.h 中完整。否则,编译器在TEST 中定义变量时会报错。

如果未定义,您还必须定义 operator&lt;&lt;(std::ostream&amp;, const pcl::PointXYZ&amp;),以便在相等断言失败时 Google Test 可以打印出您的值。

【讨论】:

    猜你喜欢
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 2021-09-03
    相关资源
    最近更新 更多