template<class T> class A {
template<class T2>
friend void operator+(A const& lhs, A<T2> const& rhs) {}
};
template<class T> class B : public A<T> {};
int main(int, char**) {
B<int> a, b;
a + b;
return 0;
}
это работает. Ассиметрия в +
(один шаблон, один - нет) гарантирует, что несколько A
не конфликтуют с их +
.
В некоторых ситуациях вам действительно нужно, чтобы lhs был экземпляром B
:
template<class T> struct A {
template<class D, class T2, std::enable_if_t<std::is_base_of<A, D>{}, bool> =true >
friend void operator+(D const& lhs, A<T2> const& rhs) {
std::cout << D::name() << "\n";
}
static std::string name() { return "A"; }
};
template<class T> struct B : public A<T> {
static std::string name() { return "B"; }
};
int main(int, char**) {
B<int> a, b;
a + b;
return 0;
}
, который использует A
operator+
, но LHS имеет тип B
. Делать это для B<T2>
на правой стороне не очень жизнеспособно, это становится смешным.