Hasta el estándar C ++ 20 de C ++, cuando queríamos definir un operador fuera de clase que usara algunos miembros privados de una clase de plantilla, usaríamos una construcción similar a esta:
template <typename T>
class Foo;
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs);
template <typename T>
class Foo {
public:
constexpr Foo(T k) : mK(k) {}
constexpr friend bool operator==<T>(T lhs, const Foo& rhs);
private:
T mK;
};
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs) {
return lhs == rhs.mK;
}
int main() {
return 1 == Foo<int>(1) ? 0 : 1;
}
Sin embargo, desde C ++ 20, podemos omitir la declaración fuera de clase, por lo tanto, también la declaración de reenvío, por lo que podemos salir con solo:
template <typename T>
class Foo {
public:
constexpr Foo(T k) : mK(k) {}
constexpr friend bool operator==<T>(T lhs, const Foo& rhs);
private:
T mK;
};
template <typename T>
constexpr bool operator==(T lhs, const Foo<T>& rhs) {
return lhs == rhs.mK;
}
Ahora, mi pregunta es, ¿qué parte de C ++ 20 nos permite hacerlo? ¿Y por qué no era esto posible en estándares anteriores de C ++?
Como se señaló en los comentarios, clang no acepta este código presentado en la demostración, lo que sugiere que esto podría ser un error en gcc.
Archivé un informe de error en bugzilla de gcc
"c string" == Foo<std::string>("foo")
)).