I have a simple unit-test using Catch 2.11.1:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <utility>
#include <any>
namespace A::B
{
namespace C
{
struct S
{
};
}
using type = std::pair<C::S, std::any>;
}
inline bool operator==(A::B::type const&, A::B::type const&)
{
return true;
}
TEST_CASE("test", "[test]")
{
auto t1 = std::make_pair(A::B::C::S(), std::any());
auto t2 = std::make_pair(A::B::C::S(), std::any());
REQUIRE(t1 == t2);
}
The above simple programs generates the following errors:
$ g++ -Wall -Wextra -Wpedantic test-single.cpp -std=c++17
In file included from /usr/include/c++/9/bits/stl_algobase.h:64,
from /usr/include/c++/9/bits/char_traits.h:39,
from /usr/include/c++/9/string:40,
from catch.hpp:457,
from test-single.cpp:2:
/usr/include/c++/9/bits/stl_pair.h: In instantiation of ‘constexpr bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = A::B::C::S; _T2 = std::any]’:
catch.hpp:2289:98: required from ‘bool Catch::compareEqual(const LhsT&, const RhsT&) [with LhsT = std::pair<A::B::C::S, std::any>; RhsT = std::pair<A::B::C::S, std::any>]’
catch.hpp:2318:34: required from ‘const Catch::BinaryExpr<LhsT, const RhsT&> Catch::ExprLhs<LhsT>::operator==(const RhsT&) [with RhsT = std::pair<A::B::C::S, std::any>; LhsT = const std::pair<A::B::C::S, std::any>&]’
test-single.cpp:28:5: required from here
/usr/include/c++/9/bits/stl_pair.h:449:24: error: no match for ‘operator==’ (operand types are ‘const A::B::C::S’ and ‘const A::B::C::S’)
449 | { return __x.first == __y.first && __x.second == __y.second; }
| ~~~~~~~~~~^~~~~~~~~~~~
[And many many more messages after this...]
The crucial part of the error message is this line:
/usr/include/c++/9/bits/stl_pair.h: In instantiation of ‘constexpr bool std::operator==(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = A::B::C::S; _T2 = std::any]’:
From the error message it's clear that it's the standard std::operator==
function for std::pair
that is being invoked, instead of my overloaded operator==
function.
If I don't do the comparison inside the Catch REQUIRE
macro, then it works:
auto result = t1 == t2; // Invokes my overloaded comparison operator
REQUIRE(result);
Now is this a problem with Catch, or with my operator function?
NB: I'm building on Debian SID with a recent build of GCC 9.2
$ g++ --version
g++ (Debian 9.2.1-23) 9.2.1 20200110
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
REQUIRE
does differently? – Gobert==
and so ADL is not being relied on right? Cos that function is in scope. – Emaciationoperator==
declared between the==
in the code and his user-defined one in the global namespace. But I'm really not inclined to dissect the macro. – Annamariaannamariet1 == t2
is not actually evaluated in the normal way. My tests are full of added()
:D – Emaciation==
. And unqualified lookup in general. en.cppreference.com/w/cpp/language/adl. But I assume the difference comes from dependent name lookup in a template (which does ADL only, see the end of the page) vs normal unqualified lookup. – Annamariaannamarie==
(i.e. not the version steeped in a few calls into Catch2 machinery). I do agree with your conclusion though; that sounds reasonable – Emaciation