在类型树中查找最近祖先类型的技术实现问询
实现
nearest_ancestor 类型特性 针对你构建的类型树,我们可以通过提取父类型、递归遍历父链的方式实现需求:找到从根节点到目标节点路径上,紧邻根节点的下一级节点(即目标节点的祖先链中,父节点为根的那个节点)。
1. 提取节点的父类型
首先定义parent_type特性,用于从Node派生类中提取其父类型参数:
#include <type_traits> // 前置声明Node类 template <typename T, typename PARENT, typename ... CHILDREN> class Node; // 基础模板:非Node派生类触发编译错误 template <typename T> struct parent_type { static_assert(std::is_base_of_v<Node<T, void>, T>, "T must be a class derived from Node"); }; // 特化模板:提取Node的PARENT参数 template <typename T, typename PARENT, typename... CHILDREN> struct parent_type<Node<T, PARENT, CHILDREN...>> { using type = PARENT; }; // 辅助别名,简化类型引用 template <typename T> using parent_type_t = typename parent_type<T>::type;
2. 验证后代关系(可选)
为了避免传入非后代类型导致的无意义递归,定义is_descendant特性判断一个类型是否是另一个的后代(含自身):
// 判断Descendant是否是Ancestor的后代 template <typename Descendant, typename Ancestor> struct is_descendant { static constexpr bool value = std::is_same_v<Descendant, Ancestor> || (!std::is_same_v<parent_type_t<Descendant>, void> && is_descendant<parent_type_t<Descendant>, Ancestor>::value); }; template <typename Descendant, typename Ancestor> constexpr bool is_descendant_v = is_descendant<Descendant, Ancestor>::value;
3. 实现 nearest_ancestor 特性
通过递归遍历目标节点的父链,直到找到父节点为根节点的节点,该节点即为所求:
// 基础模板声明 template <typename Root, typename Descendant, typename = void> struct nearest_ancestor; // 边界情况:目标节点就是根节点时,返回void(可根据需求自定义) template <typename Root> struct nearest_ancestor<Root, Root> { using type = void; }; // 终止条件:当前节点的父节点是根节点,返回当前节点 template <typename Root, typename Descendant> struct nearest_ancestor<Root, Descendant, std::enable_if_t<std::is_same_v<parent_type_t<Descendant>, Root>>> { using type = Descendant; }; // 递归情况:当前节点的父不是根节点,继续向上遍历父链 template <typename Root, typename Descendant> struct nearest_ancestor<Root, Descendant, std::enable_if_t<!std::is_same_v<parent_type_t<Descendant>, Root> && !std::is_same_v<Descendant, Root>>> { static_assert(is_descendant_v<Descendant, Root>, "Descendant must be a descendant of Root"); using type = typename nearest_ancestor<Root, parent_type_t<Descendant>>::type; }; // 辅助别名,简化类型引用 template <typename Root, typename Descendant> using nearest_ancestor_t = typename nearest_ancestor<Root, Descendant>::type;
测试验证
结合你的类型树进行测试,以下断言均会通过:
// 你的类型树定义 template <typename T, typename PARENT, typename ... CHILDREN> class Node {}; class X; class A; class AA; class AB; class B; class BA; class BB; class X : public Node<X, void, A, B> {}; class A : public Node<A, X, AA, AB> {}; class AA : public Node<AA, A> {}; class AB : public Node<AB, A> {}; class B : public Node<B, X, BA, BB> {}; class BA : public Node<BA, B> {}; class BB : public Node<BB, B> {}; // 测试用例 static_assert(std::is_same_v<nearest_ancestor_t<X, BB>, B>, "BB's nearest ancestor relative to X is B"); static_assert(std::is_same_v<nearest_ancestor_t<X, A>, A>, "A's nearest ancestor relative to X is A"); static_assert(std::is_same_v<nearest_ancestor_t<A, AA>, AA>, "AA's nearest ancestor relative to A is AA"); static_assert(std::is_same_v<nearest_ancestor_t<X, X>, void>, "X's nearest ancestor relative to X is void");
内容的提问来源于stack exchange,提问作者Patrick Wright
相关产品推荐
相关产品推荐

