9

我有一个问题,我需要发现两种类型(具有一个或零个基类)的共同祖先(如果存在)。是否有可能建立一个类型特征来解决这个问题?在代码中:

template<typename T1, typename T2>
  struct closest_common_ancestor
{
  typedef XXX type;  // what goes here?
};

给定以下类型:

struct root {};
struct child1 : root {};
struct child2 : root {};
struct child3 : child2 {};
struct unrelated {};

closest_common_ancestor将导致以下类型:

closest_common_ancestor<root, child1>::type == root
closest_common_ancestor<child1, child2>::type == root
closest_common_ancestor<child3, child1>::type == root
closest_common_ancestor<child3, child2>::type == child2
closest_common_ancestor<unrelated, child1>::type == error

我相信如果我可以检查一个类型是否有零个或一个基类,如果有,那么我可以解决这个问题,如果是,那么该类型的名称。这可能吗?

4

1 回答 1

7

正如 K-ballo 所提到的,不幸的是,不可能获得一个类所拥有的基础列表(太糟糕了......)。

如果您手动注释您的类(例如,定义一个简单std::tuple<>的基础列表),那么您可以使用此信息。当然,更简单的方法是使用特征:

template <typename> struct list_bases { typedef std::tuple<> type; };

然后你可以为你的类型专门化这个特征:

template <> struct list_bases<child1> { typedef std::tuple<root> type; };

从那里开始,您可以开始尝试寻找祖先……但这可能不会立即发生。除了实现细节(递归获取基数,实现“距离”选择)之外,我预计会出现“奇怪”案例的问题。

在通常的(线性)继承层次结构中,距离选择可以通过使用 和 的组合来解决is_base_ofis_same但请考虑以下层次结构:

struct root1 {}; struct root2 {};

struct child1: root1 {}; struct child2: root2 {};

struct child12: root1, child2 {}; struct child21: root2, child1 {};

现在,child12child21两个共同的祖先:root1root2......哪个是最接近的?

它们是等价的。考虑我添加:

struct root3 {}; struct child31: root3, child1 {};

然后是和root1的共同祖先。child12child21child31

但是,如果我绕开定义,closest_common_ancestor随意定义closest_common_ancesotr<child12, child21>就是root2,那么我找不到任何共同的祖先child31

因此,我的建议是列出所有最近的祖先,并用于tuple实现集合操作。

于 2011-11-03T20:28:35.473 回答