Вот пример (наивной) попытки:
template<class T1, class T2> class MatchableFor
{
public:
MatchableFor(): what(0)
{
if(настоящий класс это не T1 и не T2, узнается с помощью (2) )
throw SomeError;
else if( настоящий класс это T1 )
what=1;
else if( настоящий класс это T2 )
what=2;
}
virtual void run(Runnable< MatchableFor<T1,T2> > r1, Runnable< MatchableFor<T1,T2> > r2)
{
what==0 ? throw SomeError :
what==1 ? r1.run(dynamic_cast<T1*>this) :
what==2 ? r2.run(dynamic_cast<T2*>this) :
throw SomeError;
}
private:
int what;
};
class Child1;
class Child2;
struct Parent: public MatchableFor<Child1, Child2>
{
virtual void do_something()=0;
};
class Child1: public Parent { void do_something() { f(); } }; // ok
class Child2: public Parent { void do_something() { g(); } }; // ok
class Child3: public Parent { void do_something() { h(); } }; // а вот это можно недопустить с помощью (1)
вроде бы (2) вообще невозможно, а (1) и (3) мне неизвестно