2016-08-09 10 views
3

クラス階層内の二つのクラスの共通の親を見つけること:どのように私は次のように単一継承のクラス階層が定義されている

struct A  { using Parent = void; void fnct() { std::cout << "A\n"; } }; 
struct AA : A { using Parent = A;  void fnct() { std::cout << "AA\n"; } }; 
struct AB : A { using Parent = A;  void fnct() { std::cout << "AB\n"; } }; 
struct AAA : AA { using Parent = AA; void fnct() { std::cout << "AAA\n"; } }; 
struct AAB : AA { using Parent = AA; void fnct() { std::cout << "AAB\n"; } }; 
struct ABA : AB { using Parent = AB; void fnct() { std::cout << "ABA\n"; } }; 
struct ABB : AB { using Parent = AB; void fnct() { std::cout << "ABB\n"; } }; 
階層内の各クラスには、その直接の親クラスにエイリアス Parentを定義

、およびメンバー関数void fnct()

I親型PまでオブジェクトタイプCからメンバ関数fnct()のすべてを呼び出すクラスCの指定されたオブジェクトとクラス階層の所与の親クラスPため、テンプレート関数call_fnct_upto_parent<P,C>(C&)を定義するために必要。限りPCの親であると期待されるような作品上で定義された

template<class P, class C> 
typename std::enable_if<!std::is_same<P,C>::value,void>::type call_fnct_upto_parent(C& c) 
{ 
    c.fnct(); 
    static_assert(!std::is_same<typename C::Parent,void>::value, "parent not found"); 
    call_fnct_upto_parent<P, typename C::Parent>(c); 
} 

template<class P, class C> 
typename std::enable_if<std::is_same<P,C>::value,void>::type call_fnct_upto_parent(C& c) 
{ 
    c.fnct(); 
} 

機能call_fnct_upto_parent<P,C>(C&)を次のように私はSFINAEを使用して、これを実装しました。たとえば、call_fnct_upto_parent<A>(aaa)aaaのタイプがAAAのコール)は、コンパイル時に解決されたaaa.AAA::fnct(),aaa.AA::fnct()およびaaa.A::fnct()へのその後の呼び出しになります。

さて、クラスCoの指定されたオブジェクトとクラス階層の指定されたクラスChため、タイプまで、オブジェクト型Coからメンバ関数fnct()の全てを呼び出し、テンプレート関数call_fnct_upto_common_parent<Ch,Co>(Co&)を定義したいと思いクラスChおよびCoに最も近い共通の親のP。例として、AがクラスABおよびAAAに最も近い共通の親であるため、call_fnct_upto_common_parent<AB>(aaa)を呼び出すと、aaa.AAA::fnct(),aaa.AA::fnct()およびaaa.A::fnct()に続くコールが発生します。

このような機能はどのように実装できますか?可能であれば、コンパイル時に解決されたコールを持つソリューションが望ましいでしょう。

ありがとうございました。

答えて

3

あなたの既存のコードに類似した構造を持つstd::is_base_ofを使用することができます。

template<class T, class U> 
typename std::enable_if<!std::is_base_of<U,T>::value,void>::type 
call_fnct_upto_common_parent(U& u) 
{ 
    u.fnct(); 
    static_assert(!std::is_same<typename U::Parent,void>::value, "parent not found"); 
    call_fnct_upto_common_parent<T, typename U::Parent>(u); 
} 

template<class T, class U> 
typename std::enable_if<std::is_base_of<U,T>::value,void>::type 
call_fnct_upto_common_parent(U& u) 
{ 
    u.fnct(); 
} 
+0

そのような単純な... ''のstd :: is_base_of <>知りませんでした。完璧にうまくいく、ありがとう。 – shrike

関連する問題