#include <iostream>

template <typename Derived>
struct A
{
  static void do_thing() { Derived::do_thing_impl(); }
};

struct B : public A<B>
{
  friend A<B>;
 protected:
  static void do_thing_impl() { std::cout << "B impl" << std::endl; }
};

struct C : public A<C>
{
  friend A<C>;
 protected:
  static void do_thing_impl() { std::cout << "C impl" << std::endl; }
};

struct D : public A<D>
{
 friend A<D>;
};

int main() 
{
 A<B>::do_thing();
 A<C>::do_thing();
 A<D>::do_thing();

 return (0);
}