I have the following code, where a library defines a few types in the lib namespace including a wrap type template. It also defines the operator+ for the template but checks the operator+ on the wrapped type for determining the return type -
#include
#include
namespace lib {
template
class named_type {};
template
class wrap {};
template() + std::declval())>
auto operator + (const wrap&, const int&) -> RetType {
return RetType{};
}
} // end of lib namespace
// User code
const char foo_t_name[] = "FooT";
using foo_t = lib::named_type;
foo_t operator + (const foo_t&, const int&) {
return foo_t{};
}
const char bar_t_name[] = "BarT";
using bar_t = lib::named_type;
namespace lib { // example where the operator is wrapped in lib namesapce
bar_t operator + (const bar_t&, const int&) {
return bar_t{};
}
}
int main(int, char**) {
lib::wrap x;
x + 1;
lib::wrap y;
y + 1;
return 0;
}
The user now creates a type (alias) in the global namespace by defining the name for the type and defines the operator+ in the global namespace (foo_t). This code compiles with gcc-11.4 (Compiler Explorer links below), but fails to compile with gcc-12.1. If the operator definition is wrapped in the lib namespace (bar_t), both compilers compile it happily.
If I understand this correctly, the operator+ for wrap is not able to find the operator+ for lib::named_type because it is outside the namespace. However, at the point of instantiation (in the main function), the operator is available in the global namespace. Shouldn't it be able to resolve it? Also since one of the compiler compiles this correctly, is one of the compiler wrong or is this an implementation defined behavior? This is C++11, if that matters.