Até o padrão C ++ 20 do C ++, quando queríamos definir um operador fora da classe que usa alguns membros privados de uma classe de modelo, usaríamos uma construção semelhante 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;
}
Desde C ++ 20, no entanto, podemos omitir a declaração fora da classe, assim também a declaração direta, para que possamos nos safar apenas:
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;
}
Agora, minha pergunta é: qual parte do C ++ 20 nos permite fazer isso? E por que isso não foi possível nos padrões anteriores do C ++?
Como foi apontado nos comentários, o clang não aceita esse código apresentado na demonstração, o que sugere que isso pode realmente ser um bug no gcc.
Arquivei um relatório de bug no bugzilla de gcc
"c string" == Foo<std::string>("foo")
)).