我正在使用Google Test v1.7
我创建了一个自定义updateAlert
operator ==
找不到,但如果直接使用,可以找到。这是代码
ASSERT_EQ
#include <vector>
#include <deque>
#include "gtest/gtest.h"
template< typename T> struct bar { T b; };
template< typename T>
bool operator == ( const std::vector<T>& v, const bar<T>& b ) { return false; }
template< typename T>
bool operator==( const std::vector<T>& v , const std::deque<T>& d) { return false; }
TEST( A, B ) {
std::vector<char> vec;
std::deque<char> deq;
bar<char> b;
// compiles
ASSERT_EQ( vec, b );
// compiles
vec == deq;
// doesn't compile
ASSERT_EQ( vec, deq );
}
行会产生Apple 6.0 clang的以下消息:
ASSERT_EQ( vec, deq )
虽然gcc 4.7.2列出了它尝试过但未能使test/gtest.h:18861:16: error: invalid operands to binary expression ('const std::__1::vector<char, std::__1::allocator<char> >' and 'const
std::__1::deque<char, std::__1::allocator<char> >')
if (expected == actual) {
~~~~~~~~ ^ ~~~~~~
../x86_64-linux_debian-7/tests/gtest/gtest.h:18897:12: note: in instantiation of function template specialization 'testing::internal::CmpHelperEQ<std::__1::vector<char,
std::__1::allocator<char> >, std::__1::deque<char, std::__1::allocator<char> > >' requested here
return CmpHelperEQ(expected_expression, actual_expression, expected,
^
tst.cc:27:5: note: in instantiation of function template specialization 'testing::internal::EqHelper<false>::Compare<std::__1::vector<char, std::__1::allocator<char> >,
std::__1::deque<char, std::__1::allocator<char> > >' requested here
ASSERT_EQ( vec, deq );
^
工作的所有模板,忽略了我提供的模板。
我不明白是为什么
expected == actual
找到提供的ASSERT_EQ( vec, b )
;和operator ==
编译;但vec == deq
没有。有人可以对此有所启发吗?它必须是非常明显的东西,但我看不到它。
答案 0 :(得分:4)
您的问题是由ADL(依赖于参数的查找)引起的。正如您所知,std::vector
和std::deque
在std
命名空间中定义,但您正在全局命名空间中定义operator==
,并且ADL无法找到此函数。< / p>
要解决您的问题,您必须在容器的同一命名空间中定义operator==
,即std
命名空间内。问题是你不允许这样做。通过这种方式,我建议你改变一下你的方法。为什么不试试这样的事情:
template< typename T>
bool equal( const std::vector<T>& v , const std::deque<T>& d) { return false; }
TEST( A, B ) {
std::vector<char> vec;
std::deque<char> deq;
ASSERT_TRUE( equal(vec, deq) );
}
答案 1 :(得分:1)
答案简短:
无法找到正确的operator==
模板主要是因为Google Test定义了自己的operator==
模板,而不使用ADL的命名空间查找规则选择了该模板并拒绝它。正如Amadeus所指出的,ADL无法找到我定义的模板。
解决方案:
正如Amadeus指出的那样,不鼓励将事物移入std
命名空间(在这种情况下是为了让ADL起作用)。
我毫不犹豫地污染了Google Test的命名空间,因此将我的模板移到::testing::internals
可以解决问题(使用普通查找,而不是ADL)。
答案越长:
我的期望是全局operator==
应该通过Vandevoorde & Josuttis, C++ Templates第9.2节,p。 122,术语普通查找。
以下代码说明了这一点:
#include <vector>
#include <deque>
template< typename T>
bool operator==( const std::vector<T>& v , const std::deque<T>& d);
namespace A {
template <typename T1, typename T2>
bool EQ( const T1& expected, const T2& actual ) {
return expected == actual;
}
}
void TestBody() {
std::vector<char> vec;
std::deque<char> deq;
::A::EQ(vec, deq) ;
}
这成功编译。我读到Amadeus&#39;答案是Amadeus认为应该因ADL而失败。但是,在这种情况下,ADL 不用于查找operator==
。这可以通过重写
expected == actual
作为
return (operator==)( expected, actual);
V&J第9.2.1节,第123页:
如果要调用的函数的名称括在括号中,也会禁止ADL
在这种情况下代码仍然可以编译。
为了确定涉及Google Test的代码失败的原因,我对Google Test标题执行了相当极端的手术,直到我只提取导致编译器错误的代码,从而导致operator==
的定义{ {1}}中的{1}}命名空间:
testing::internal
将其翻译成我的测试代码会导致:
gtest/internal/gtest-linked_ptr.h
这成功无法使用未解决的模板错误进行编译。有趣的是失败的第一个信息:
namespace testing {
namespace internal {
[...]
template<typename T> inline
bool operator==(T* ptr, const linked_ptr<T>& x) {
return ptr == x.get();
}
[...]
}
}
所以,它首先看#include <vector>
#include <deque>
template< typename T>
bool operator==( const std::vector<T>& v , const std::deque<T>& d);
namespace A {
struct S {};
template<typename T> bool operator==(T* ptr, S& x);
template <typename T1, typename T2>
bool EQ( const T1& expected, const T2& actual ) {
return expected == actual;
}
}
void TestBody() {
std::vector<char> vec;
std::deque<char> deq;
::A::EQ(vec, deq) ;
}
。
Stroustrup, The C++ Programming Language, 4th Edition,第26.3.5节。 753指出依赖名称的绑定是通过查看
来完成的在这种情况下,根据第一条规则,应选择gtst.cc: In instantiation of ‘bool A::EQ(const T1&, const T2&) [with T1 = std::vector<char>; T2 = std::deque<char>]’:
gtst.cc:25:21: required from here
gtst.cc:14:37: error: no matching function for call to ‘operator==(const std::vector<char>&, const std::deque<char>&)’
gtst.cc:14:37: note: candidates are:
gtst.cc:10:31: note: template<class T> bool A::operator==(T*, A::S&)
gtst.cc:10:31: note: template argument deduction/substitution failed:
gtst.cc:14:37: note: mismatched types ‘T*’ and ‘std::vector<char>’
而不是A::operator==
。 ADL也找不到A::operator==
,因为正如Amadeus指出的那样,它不在::operator==
命名空间中。
为了说服自己编译失败确实是第一条规则的结果,我将::operator==
的定义移到了std
命名空间中,并像以前一样关闭了ADL。
代码成功编译。