C++ only gives you two ways to name friends:
friend class C; // a specific class
template <typename T>
friend class S; // friend the class template S
There's no way to stick in a metafunction in there, which would look hypothetically something like this:
template <typename T>
friend enable_if_t<std::is_base_of<Base, T>::value, T>;
But I guess if you're open to horrible hackery (this phrase should be interpreted as never do this ever please god no, but it's at least marginally amusing), you could simply implement all of your derived types as explicit specializations of some template.
struct Base { ... };
template <typename > class Derived;
struct A_tag { };
template <>
class Derived<A_tag> : Base {
template <typename T>
friend class Derived;
...
};
using A = Derived<A_tag>;
If we do similar thing for B
, C
, etc., then A
, B
, and C
are mutually all friends - since under the hood they're really Derived<A_tag>
, Derived<B_tag>
, and Derived<C_tag>
and thus the friend class template statement covers all of them.