`is_base_of` 是如何工作的?

时间:2023-02-23
本文介绍了`is_base_of` 是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

下面的代码是如何工作的?

How does the following code work?

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 sample
class Base {};
class Derived : private Base {};

//Expression is true.
int test[is_base_of<Base,Derived>::value && !is_base_of<Derived,Base>::value];

  1. 请注意,B 是私有库.这是如何运作的?

  1. Note that B is private base. How does this work?

请注意,operator B*() 是常量.为什么重要?

Note that operator B*() is const. Why is it important?

为什么 templatestatic yes check(D*, T);static yes check(B*, int); 好吗?

Why is template<typename T> static yes check(D*, T); better than static yes check(B*, int); ?

注意:它是boost::is_base_of的精简版(删除了宏).这适用于各种编译器.

Note: It is reduced version (macros are removed) of boost::is_base_of. And this works on wide range of compilers.

推荐答案

如果它们是相关的

让我们暂时假设 B 实际上是 D 的基础.然后对于 check 的调用,两个版本都是可行的,因为 Host 可以转换为 D* and B*.它是一个用户定义的转换序列,如 13.3.3.1.2 所述,从 HostD*B* 分别.为了寻找可以转换类的转换函数,根据13.3.1.5/1

If they are related

Let's for a moment assume that B is actually a base of D. Then for the call to check, both versions are viable because Host can be converted to D* and B*. It's a user defined conversion sequence as described by 13.3.3.1.2 from Host<B, D> to D* and B* respectively. For finding conversion functions that can convert the class, the following candidate functions are synthesized for the first check function according to 13.3.1.5/1

D* (Host<B, D>&)

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

The first conversion function isn't a candidate, because B* can't be converted to D*.

对于第二个函数,存在以下候选:

For the second function, the following candidates exist:

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

那些是采用宿主对象的两个转换函数候选.第一个通过 const 引用获取它,第二个没有.因此,第二个是 13.3.3.2/3b1sb4 对非常量 *this 对象(隐含对象参数)的更好匹配,并且是用于转换为 B* 用于第二个 check 函数.

Those are the two conversion function candidates that take the host object. The first takes it by const reference, and the second doesn't. Thus the second is a better match for the non-const *this object (the implied object argument) by 13.3.3.2/3b1sb4 and is used to convert to B* for the second check function.

如果您要删除常量,我们将有以下候选

If you would remove the const, we would have the following candidates

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

这意味着我们不能再通过常量进行选择.在普通的重载解析方案中,调用现在是不明确的,因为通常返回类型不会参与重载解析.然而,对于转换函数,有一个后门.如果两个转换函数一样好,那么他们的返回类型根据13.3.3/1决定谁最好.因此,如果您要删除常量,则将采用第一个,因为 B* 转换为 B* 比将 D* 转换为 <代码>B*.

This would mean that we can't select by constness anymore. In an ordinary overload resolution scenario, the call would now be ambiguous because normally the return type won't participate in overload resolution. For conversion functions, however, there is a backdoor. If two conversion functions are equally good, then the return type of them decides who is best according to 13.3.3/1. Thus, if you would remove the const, then the first would be taken, because B* converts better to B* than D* to B*.

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

Now what user defined conversion sequence is better? The one for the second or the first check function? The rule is that user defined conversion sequences can only be compared if they use the same conversion function or constructor according to 13.3.3.2/3b2. This is exactly the case here: Both use the second conversion function. Notice that thus the const is important because it forces the compiler to take the second conversion function.

既然我们可以比较它们 - 哪个更好?规则是从转换函数的返回类型到目标类型的更好的转换获胜(再次通过 13.3.3.2/3b2).在这种情况下,D* 转换为 D* 比转换为 B* 更好.这样第一个函数就被选中了,我们就认出了继承!

Since we can compare them - which one is better? The rule is that the better conversion from the return type of the conversion function to the destination type wins (again by 13.3.3.2/3b2). In this case, D* converts better to D* than to B*. Thus the first function is selected and we recognize the inheritance!

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

Notice that since we never needed to actually convert to a base class, we can thereby recognize private inheritance because whether we can convert from a D* to a B* isn't dependent on the form of inheritance according to 4.10/3

现在让我们假设它们没有继承关系.因此对于第一个函数,我们有以下候选

Now let's assume they are not related by inheritance. Thus for the first function we have the following candidates

D* (Host<B, D>&) 

第二个我们现在有另一套

And for the second we now have another set

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

由于没有继承关系就不能将D*转换为B*,所以现在两个用户定义的转换序列之间没有通用的转换函数!因此,如果不是因为第一个函数是模板,我们将模棱两可.根据13.3.3/1,当存在同样好的非模板函数时,模板是第二选择.因此,我们选择了非模板函数(第二个),我们认识到BD 之间没有继承!

Since we cannot convert D* to B* if we haven't got a inheritance relationship, we now have no common conversion function among the two user defined conversion sequences! Thus, we would be ambiguous if not for the fact that the first function is a template. Templates are second choice when there is a non-template function that is equally good according to 13.3.3/1. Thus, we select the non-template function (second one) and we recognize that there is no inheritance between B and D!

这篇关于`is_base_of` 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:std::function 与模板 下一篇:用于显式特化模板类中的模板函数的 C++ 语法?

相关文章

最新文章