#include #include template struct notify_tag {}; template void notify(T*t); template< typename T> struct dispatcher { static void dispatch(...) { std::cout<<"T("< base"<*) { std::cout<<"T("< base; ";t->notify(); } template static void dispatch(T*t,notify_tag*) { std::cout<<"T("< base with T!=U; ";t->U::notify(); } }; template void notify(T*t) { dispatcher::dispatch(t,t); } struct enable_shared_from_this : notify_tag { void notify() { std::cout<<"enable_shared_from_this"< { void notify() { std::cout<<"shared_ptr_debugger"<, // so it doesn't work automatically. struct C3 : enable_shared_from_this, shared_ptr_debugger {}; struct C4 : enable_shared_from_this, shared_ptr_debugger, notify_tag { void notify() { std::cout<<"C4 now delegating to its base classes"<(this)); ::notify(static_cast(this)); } }; int main() { C0 c0; C1 c1; C2 c2; C3 c3; C4 c4; notify(&c0); notify(&c1); notify(&c2); notify(&c3); notify(&c4); }