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

发布于 2024-11-03 03:07:22 字数 869 浏览 0 评论 0原文

我正在解决一个很好的问题,关于如何在 boost 中实现 is_base_of (这决定了是否一个给定的在编译时是另一个的基础]

第一次看到这样的代码,我很惊讶事情如何能够如此顺利地工作!但是,我对许多步骤感到困惑(在阅读了所有答案之后),因此,我想知道是否可以替代地实现此功能:

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 * 将始终具有不同的大小,并避免典型的“是”和“否”的类型转换]

I was going through a nice question for how is_base_of is implemented in boost (which decides if a given class is a base of another class at compile time].

Seeing such code for the 1st time, I got amazed that how things can be made to work so nicely! However, many steps I got confused to understand (after reading all the answers). So, I was wondering that if this functionality can be implemented alternatively. I tried following:

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*));
};

It works fine as per expectation for the general case.

The only problem is for private/protected inheritance. It goes and choose the expected function, but also shows error as:- is an inaccessible base of .... I would appreciate if someone can suggest any little modification missing to the code to solve this problem (If not the functionality wise then at least to get rid of the error message).

[Note: I have assume that char and B* will always be of different sizes and avoided typecasting of typical 'yes' and 'no']

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瑾兮 2024-11-10 03:07:22

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

但是,在您的代码中,如果类相关,则对 check 的调用确实会利用从 Child* 转换为 B* 的继承。这恐怕无法轻易解决,因为您提出的方法非常不同。

如果相关

您的解决方案

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

链接的解决方案

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

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

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

如果不相关

您的解决方案

Child 不是 B,因此是 Check 的第一个版本不是一个选择。第二个版本是可行的,因为 Child 仍然是 dummy,因此可以从 dummy 进行专门化。由于只有一种选择,因此选择是微不足道的。

链接的解决方案

对于 check 的第一个版本:Host 通过以下方式转换为 D*用户定义的转换。

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

如果不是只有一个版本的 check 函数具有模板参数这一事实,这些路径将是无法比较的。

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

I think the key part in the linked solution was that no matter what the end result would be (related or unrelated) - the chosen conversion sequence wouldn't actually include the inheritance that is tested for. Compiler is taking it into consideration in the process of selecting the appropriate version of the check function. However each time in the end the path selected wouldn't actually use it.

In your code however if the classes are related, the call to check indeed does make use of the inheritence converting from Child* to B*. And this - I'm afraid cannot be fixed easily as the approach that you presented is very different.

If related

Your solution

Child is D therefore is also B. Therefore there exists conversion from Child* to B*. So the first version of Check is viable. The second version of Check is viable as well as Child is also dummy<int> and therefore Child* is dummy<int>*. The first version is selected as this doesn't involve template parameter specialization.

The linked solution

For the first version of check: Host<B, D> is converted via user defined conversion to D*. The conversion result type exactly matches the function argument. No inheritance is used here.

For the second version of check: Host<B, D> is converted again via user defined conversion to D*. The conversion result type is D* which can be further converted to B* in order to match the function argument. Inheritance is indeed used here.

However in the end compiler chooses the first version as it was noted the conversion result better matches the argument of check.

If unrelated

Your solution

Child isn't B therefore the first version of Check is not an option. Second version is viable as the Child is still dummy<int> therefore can be specialized from dummy<T>. As there is only one option the choice is trivial.

The linked solution

For the first version of check: Host<B, D> is converted to D* via user defined conversion.

For the second version of check: Host<B, D> is converted to const Host<B, D> and then to B* via user defined conversion.

The paths would be incomparable if it were not for the fact that only one version of check function has template arguments.

As you can see the two approaches are significantly different.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文