【问题标题】:How to find the common parent of two classes in a class hierarchy如何在类层次结构中找到两个类的共同父级
【发布时间】:2016-08-09 14:43:01
【问题描述】:

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

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&lt;P,C&gt;(C&amp;),对于给定类C的对象和给定的类层次结构的父类P,从对象类型调用所有成员函数fnct() C 直到父类型 P。我使用 SFINAE 实现了这一点,如下所示:

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

只要PC 的父级,上面定义的函数call_fnct_upto_parent&lt;P,C&gt;(C&amp;) 就可以正常工作。例如,对call_fnct_upto_parent&lt;A&gt;(aaa) 的调用,其中aaa 的类型为AAA,会导致对aaa.AAA::fnct()aaa.AA::fnct()aaa.A::fnct() 的后续调用,并在编译时解决。

现在,我想定义一个模板函数call_fnct_upto_common_parent&lt;Ch,Co&gt;(Co&amp;),它对于类Co的给定对象和类层次结构的给定类Ch,调用所有成员函数fnct()对象类型Co 直到最接近类ChCo 的公共父对象类型P。例如,对call_fnct_upto_common_parent&lt;AB&gt;(aaa) 的调用将导致对aaa.AAA::fnct()aaa.AA::fnct()aaa.A::fnct() 的后续调用,因为类A 是最接近类ABAAA 的公共父类。

这样的功能可以实现吗?如何实现?如果可行,最好在编译时解决调用。

感谢您的帮助。

【问题讨论】:

    标签: c++ inheritance parent-child sfinae


    【解决方案1】:

    您可以使用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();
    }
    

    【讨论】:

    • 就这么简单...不知道std::is_base_of&lt;&gt;;效果很好,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    相关资源
    最近更新 更多