c++ - `is_base_of` 是如何工作的?

标签 c++ templates overloading implicit-conversion typetraits

以下代码是如何工作的?

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是私有(private)基地。这是如何运作的?

  2. 请注意 operator B*()是常量。为什么它很重要?

  3. 为什么是 template<typename T> static yes check(D*, T);优于 static yes check(B*, int); ?

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

最佳答案

如果他们是相关的

让我们暂时假设 B实际上是 D 的基数.然后调用check , 这两个版本都是可行的,因为 Host可以转换为D* B* .这是一个用户定义的转换序列,如 13.3.3.1.2 所述。来自 Host<B, D>D*B*分别。为了找到可以转换类的转换函数,为第一个check合成了以下候选函数功能根据 13.3.1.5/1

D* (Host<B, D>&)

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

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

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

这是两个采用宿主对象的转换函数候选者。第一个通过 const 引用获取它,而第二个没有。因此,第二个更适合非常量 *this 13.3.3.2/3b1sb4 的对象(隐含对象参数)并用于转换为 B*第二个check功能。

如果您删除 const,我们将有以下候选者

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

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

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

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

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

如果它们不相关

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

D* (Host<B, D>&) 

第二个我们现在有了另一组

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

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

关于c++ - `is_base_of` 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2910979/

相关文章:

c++ - Visual Studio Code : C++ include path

C++ 访问编号变量

c++ - 如何获取指向专门针对字符串的模板函数的指针?

c++ - C++继承使用不同的参数重载函数

c++ - 为非本地容器(数据库后端)重载/专门化 STL 算法

c++ - 在此 C++ 代码段中,复制构造函数被调用了多少次?

c++ - 类 X 的配置类,它应该嵌套在 X 中还是 X 之外?

python - 如何在 python ctypes 中包装包含 C++ 对象的 C 结构

java - 返回未知类型 Java

python - yesno 过滤器的复杂比较?