关于C#:” is_base_of”的替代实现(检查基础/派生关系)

Alternate implementation of “is_base_of” (checking base/derived relationship)

我正在研究如何在boost中实现is_base_of(这决定了在编译时给定的class是否是另一个class的基础)的问题。

第一次看到这样的代码,我惊讶于如何使事情如此完美地工作!但是,许多步骤让我感到困惑(在阅读所??有答案之后)。因此,我想知道是否可以替代地实现此功能。我尝试了以下操作:

1
2
3
4
5
6
7
8
9
10
11
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*始终具有不同的大小,并避免了典型的"是"和"否"的类型转换]


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

但是在您的代码中,如果类是相关的,对check的调用确实的确利用了从Child*B*的继承。而且-恐怕无法轻易解决,因为您介绍的方法非常不同。

如果相关

您的解决方案

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

链接的解决方案

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

对于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函数的一个版本具有模板参数的事实,那么路径将是无与伦比的。

如您所见,这两种方法明显不同。