为了账号安全,请及时绑定邮箱和手机立即绑定

`is_base_of`是如何工作的?

`is_base_of`是如何工作的?

C++
MM们 2019-08-24 18:09:50
`is_base_of`是如何工作的?以下代码如何工作?typedef char (&yes)[1];typedef char (&no)[2];template <typename B, typename D>struct Host{   operator B*() const;   operator D*();};template <typename B, typename D>struct is_base_of{   template <typename T>    static yes check(D*, T);   static no check(B*, int);   static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);};//Test sampleclass Base {};class Derived : private Base {};//Expression is true.int test[is_base_of<Base,Derived>::value && !is_base_of<Derived,Base>::value];请注意,这B是私人基地。这是如何运作的?注意operator B*()是const。它为什么如此重要?为什么template<typename T> static yes check(D*, T);比这更好static yes check(B*, int);?注意:它是缩减版本(宏被删除)boost::is_base_of。这适用于各种编译器。
查看完整描述

3 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

如果它们是相关的

让我们暂时假设它B实际上是一个基础D。然后,对于调用check,两个版本都是可行的,因为Host可以转换为D*  B*。它是用户定义的转换序列,分别由13.3.3.1.2from 和Host<B, D>to 描述。为了找到可以转换类的转换函数,根据第一函数合成以下候选函数D*B*check13.3.1.5/1

D* (Host<B, D>&)

第一个转换函数不是候选函数,因为B*无法转换为D*

对于第二个功能,存在以下候选者:

B* (Host<B, D> const&)D* (Host<B, D>&)

这些是获取主机对象的两个转换函数候选者。第一个是const引用,第二个不是。因此,第二个是非const *this对象(隐含对象参数)的更好匹配,13.3.3.2/3b1sb4并用于转换B*为第二个check函数。

如果你要删除 const,我们会有以下候选人

B* (Host<B, D>&)D* (Host<B, D>&)

这意味着我们不能再通过constness选择了。在普通的重载解析方案中,调用现在是不明确的,因为通常返回类型不会参与重载解析。但是,对于转换函数,有一个后门。如果两个转换函数同样好,那么它们的返回类型决定谁是最好的13.3.3/1。因此,如果你想删除的常量,那么第一个将采取,因为B*转换更好的B*D*B*

现在用户定义的转换顺序更好?第二次或第一次检查功能?规则是用户定义的转换序列只有在根据它们使用相同的转换函数或构造函数时才能进行比较13.3.3.2/3b2。这就是这里的情况:两者都使用第二个转换函数。请注意,因此const很重要,因为它强制编译器采用第二个转换函数。

既然我们可以比较它们 - 哪一个更好?规则是从转换函数的返回类型到目标类型的更好转换(再次13.3.3.2/3b2)。在这种情况下,D*转换为to to D*than B*。因此选择了第一个函数,我们认识到了继承!

请注意,由于我们从未需要实际转换为基类,因此我们可以识别私有继承,因为我们是否可以从a转换D*为a B*不依赖于继承的形式根据4.10/3

如果他们没有关系

现在让我们假设它们与继承无关。因此,对于第一个功能,我们有以下候选人

D* (Host<B, D>&)

而对于第二个,我们现在有另一套

B* (Host<B, D> const&)

由于我们无法转换D*B*如果我们没有继承关系,我们现在在两个用户定义的转换序列中没有共同的转换函数!因此,如果不是第一个函数是模板的事实,我们将是模棱两可的。当有一个同样好的非模板函数时,模板是第二选择13.3.3/1。因此,我们选择非模板函数(第二个),我们认识到B和之间没有继承D


查看完整回答
反对 回复 2019-08-24
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

在你的第二个问题之后,请注意,如果它不是const,如果用B == D实例化,Host将是格式错误的。但is_base_of的设计使得每个类都是它自己的基础,因此转换运算符之一必须是const。


查看完整回答
反对 回复 2019-08-24
  • 3 回答
  • 0 关注
  • 501 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信