“is_base_of”的替代实现(检查基础/派生关系)

时间:2011-04-24 12:23:47

标签: c++ templates inheritance

我正在讨论如何在boost中实现is_base_of(在编译时确定给定的class是否是另一个class的基础]。

第一次看到这样的代码,我惊讶于如何能够很好地工作!然而,我很难理解的许多步骤(在阅读完所有答案后)。所以,我想知道如果这个功能可以替代实现。我试过以下:

template<class B, class D>
struct is_base_of
{
  template<typename T> struct dummy {};
  struct Child : D, dummy<int> {};

  static B* Check (B*);
  template<class T> static char Check (dummy<T>*);

  static const bool value = (sizeof(Check((Child*)0)) == sizeof(B*));
};

根据一般情况的预期,它可以正常工作。

唯一的问题是private/protected继承。它会选择预期的功能,但也会显示错误: - is an inaccessible base of ...。我很感激,如果有人可以建议代码中缺少任何一点修改来解决这个问题(如果不是功能明智,那么至少要摆脱错误信息)。

[注意:我假设charB*将始终具有不同的大小,并避免使用典型的“是”和“否”进行类型转换。

1 个答案:

答案 0 :(得分:2)

我认为链接解决方案的关键部分是无论最终结果是什么(相关或不相关) - 所选择的转换序列实际上不包括所测试的继承。编译器在选择适当版本的check函数的过程中会考虑它。但是,每次最终选择的路径都不会实际使用它。

在您的代码中,如果类相关,则对check的调用确实会使用从Child*转换为B*的继承。而且 - 我害怕无法轻易修复,因为你提出的方法是非常不同的。

如果相关

您的解决方案

Child D因此也是B。因此,存在从Child*B*的转换。所以Check的第一个版本是可行的。 Check的第二个版本是可行的,Child也是dummy<int>,因此Child*dummy<int>*。选择第一个版本,因为这不涉及模板参数专业化。

关联解决方案

对于check的第一个版本:Host<B, D>通过用户定义的转换转换为D*。转换结果类型与函数参数完全匹配。这里没有使用继承。

对于check的第二个版本:Host<B, D>会再次通过用户定义的转换转换为D*。转换结果类型为D*,可以进一步转换为B*以匹配函数参数。这里确实使用了继承。

然而,最后编译器选择了第一个版本,因为它注意到转换结果更好地匹配check的参数。

如果不相关

您的解决方案

Child不是B因此Check的第一个版本不是选项。第二个版本是可行的,因为Child仍然是dummy<int>因此可以从dummy<T>专门化。因为只有一个选项,所以选择是微不足道的。

关联解决方案

对于check的第一个版本:Host<B, D>通过用户定义的转化转换为D*

对于check的第二个版本:Host<B, D>已转换为const Host<B, D>,然后通过用户定义的转化转换为B*

如果不是因为只有一个版本的check函数具有模板参数,那么这些路径将是无法比拟的。

正如您所看到的,这两种方法有很大不同。

相关问题