如何在 class 层次结构中找到两个 class 的公共 parent
How to find the common parent of two classes in a class hierarchy
我有一个继承 class 层次结构,定义如下:
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"; } };
层次结构中的每个class为其直接parentclass定义了一个别名Parent
,以及一个成员函数void fnct()
.
我需要定义一个模板函数 call_fnct_upto_parent<P,C>(C&)
,对于 class C
的给定 object 和给定的 parent class class 层次结构的 P
,调用所有成员函数 fnct()
从 object 类型 C
到 parent 类型 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();
}
只要 P
是 C
的 parent,上面定义的函数 call_fnct_upto_parent<P,C>(C&)
就可以正常工作。例如,调用 call_fnct_upto_parent<A>(aaa)
,其中 aaa
的类型为 AAA
,会导致后续调用 aaa.AAA::fnct()
、aaa.AA::fnct()
和 aaa.A::fnct()
,在编译时解决。
现在,我想定义一个模板函数 call_fnct_upto_common_parent<Ch,Co>(Co&)
,对于 class Co
的给定 object 和给定的 class Ch
的 class 层次结构,调用所有成员函数 fnct()
从 object 类型 Co
到最接近的公共类型 P
parent 到 class 是 Ch
和 Co
。例如,对 call_fnct_upto_common_parent<AB>(aaa)
的调用将导致对 aaa.AAA::fnct()
、aaa.AA::fnct()
和 aaa.A::fnct()
的后续调用,因为 class A
是最接近 parent 到 classes AB
和 AAA
.
能否实现这样的功能,如何实现?如果可行,在编译时解决调用的解决方案将是更可取的。
感谢您的帮助。
您可以使用具有与现有代码类似结构的 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();
}
我有一个继承 class 层次结构,定义如下:
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"; } };
层次结构中的每个class为其直接parentclass定义了一个别名Parent
,以及一个成员函数void fnct()
.
我需要定义一个模板函数 call_fnct_upto_parent<P,C>(C&)
,对于 class C
的给定 object 和给定的 parent class class 层次结构的 P
,调用所有成员函数 fnct()
从 object 类型 C
到 parent 类型 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();
}
只要 P
是 C
的 parent,上面定义的函数 call_fnct_upto_parent<P,C>(C&)
就可以正常工作。例如,调用 call_fnct_upto_parent<A>(aaa)
,其中 aaa
的类型为 AAA
,会导致后续调用 aaa.AAA::fnct()
、aaa.AA::fnct()
和 aaa.A::fnct()
,在编译时解决。
现在,我想定义一个模板函数 call_fnct_upto_common_parent<Ch,Co>(Co&)
,对于 class Co
的给定 object 和给定的 class Ch
的 class 层次结构,调用所有成员函数 fnct()
从 object 类型 Co
到最接近的公共类型 P
parent 到 class 是 Ch
和 Co
。例如,对 call_fnct_upto_common_parent<AB>(aaa)
的调用将导致对 aaa.AAA::fnct()
、aaa.AA::fnct()
和 aaa.A::fnct()
的后续调用,因为 class A
是最接近 parent 到 classes AB
和 AAA
.
能否实现这样的功能,如何实现?如果可行,在编译时解决调用的解决方案将是更可取的。
感谢您的帮助。
您可以使用具有与现有代码类似结构的 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();
}