#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 ) ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIERlcml2ZWQ+CnN0cnVjdCBBCnsKICBzdGF0aWMgdm9pZCBkb190aGluZygpIHsgRGVyaXZlZDo6ZG9fdGhpbmdfaW1wbCgpOyB9Cn07CgpzdHJ1Y3QgQiA6IHB1YmxpYyBBPEI+CnsKICBmcmllbmQgQTxCPjsKIHByb3RlY3RlZDoKICBzdGF0aWMgdm9pZCBkb190aGluZ19pbXBsKCkgeyBzdGQ6OmNvdXQgPDwgIkIgaW1wbCIgPDwgc3RkOjplbmRsOyB9Cn07CgpzdHJ1Y3QgQyA6IHB1YmxpYyBBPEM+CnsKICBmcmllbmQgQTxDPjsKIHByb3RlY3RlZDoKICBzdGF0aWMgdm9pZCBkb190aGluZ19pbXBsKCkgeyBzdGQ6OmNvdXQgPDwgIkMgaW1wbCIgPDwgc3RkOjplbmRsOyB9Cn07CgpzdHJ1Y3QgRCA6IHB1YmxpYyBBPEQ+CnsKIGZyaWVuZCBBPEQ+Owp9OwoKaW50IG1haW4oKSAKewogQTxCPjo6ZG9fdGhpbmcoKTsKIEE8Qz46OmRvX3RoaW5nKCk7CiBBPEQ+Ojpkb190aGluZygpOwoKIHJldHVybiAoMCk7Cn0=