如何在类层次结构中找到两个类的公共父级

时间:2016-08-09 14:43:01

标签: c++ inheritance parent-child sfinae

我有一个继承类层次结构,定义如下:

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()

我需要定义一个模板函数call_fnct_upto_parent<P,C>(C&),对于类C的给定对象和类层次结构的给定父类P,它调用所有成员函数{ {1}}从对象类型fnct()到父类型C。我使用SFINAE实现了如下:

P

只要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&)的父级,上面定义的函数P就可以正常工作。例如,调用C,其中call_fnct_upto_parent<A>(aaa)的类型为aaa,会导致后续调用AAAaaa.AAA::fnct()aaa.AA::fnct(),在编译时解决。

现在,我想定义一个模板函数aaa.A::fnct(),对于类call_fnct_upto_common_parent<Ch,Co>(Co&)的给定对象和类层次结构的给定类Co,它会调用所有成员函数Ch从对象类型fnct()一直到类CoP的最近公共父类型Ch。例如,对Co的调用会导致后续调用call_fnct_upto_common_parent<AB>(aaa)aaa.AAA::fnct()aaa.AA::fnct(),因为类aaa.A::fnct()是最接近的共同父项课程AAB

可以实现这样的功能吗?如果可行的话,在编译时解决调用的解决方案将是可取的。

感谢您的帮助。

1 个答案:

答案 0 :(得分: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();
}