为什么 std::is_base_of<T, T> 当 T 是类类型时为真,而当 T 是内置类型时为假?
Why is std::is_base_of<T, T> true when T is a class type, but false when T is a built-in type?
Per[meta.rel](C++14中为20.10.6),对于类类型T
,std::is_base_of<T,T>
为true,但对于内置类型T
,std::is_base_of<T,T>
为false。通俗地说,类类型本身就是基础,但内置类型不是。这种治疗差异的动机/效用是什么?
基本原理可以追溯到很久以前,并且没有很好的文档记录。
is_base_of
最初被称为is_base_and_derived
,是在TR1中引入的。Dave Abrahams在N1541中介绍了一个针对该类的问题,编号3.13:
当前,当
X
和Y
时,is_base_and_derived<X,Y>
返回false都是一样的。这在技术上是正确的(X
不是它自己的基础class),但它没有用。定义应该放宽到当X
和Y
相同时,即使类型不同,也返回true实际上是一个类。
不幸的是,这个问题并没有说明为什么这个定义没有用处。然而,这种观点在当时并不是唯一的(2003年)。安德烈·亚历山德雷斯库两年前出版的《现代C++设计》有着大致相同的特点,在第2.7节中对其宏SUPERSUBCLASS
也有大致相同的评论,尽管如果你真的不想让一个类被视为自己的基础,这本书也添加了一个变通宏。
现代C++设计继续使用第3.12节中的SUPERSUBCLASS
按照继承顺序对Typelist进行排序。在这个练习的细节中,SUPERSUBCLASS(T, T)
是真的这一事实被利用了(为了实现的方便)。
到2004年,TR1报告N1647已经采用了这样的概念,即当T
是非并集类类型时,std::is_base_of<T,T>::value == true
是有用的。
N2255进一步阐明了is_base_of
应该如何适用于非类类型,这一变化导致了您今天看到的措辞。然而,这篇公认的论文提出的内容与以下草案(N2284)中产生的内容之间存在广泛的编辑差异。我认为编辑大大改进了措辞。
N2255为什么在非并集类类型和其他所有类型之间创建划分的原因是,is_base_of
历史上回答了关于类型继承层次结构的问题,只有一个方便的"技巧",即通过"is-a"分析可以将类视为自己的基。然而,根据该特性的多位作者的说法,不可能参与继承关系的类型永远不应该符合基类的资格。
这是否是最好的设计还有待商榷。然而,有足够的特征(例如is_class
和is_same
)可以从这些基本特征中构建你需要的任何东西。
这更多的是一段历史,而不是直截了当的"为什么"。然而,这个答案的意义在于指出is_base_of
是经过大量时间和多次迭代进化而来的。每一次迭代在当时都被认为是对以前的进化改进。
归根结底:这是委员会认为最有用的规范。但是作为规范&设计经过了多年的发展,经过几位作者的努力,还没有一份好的总体设计文件或基本原理。
内置类型不是类,非类的东西不能成为任何东西的基础。
如果有什么不同的话,我有点惊讶std::is_base_of<T,T>
即使对于类类型也是正确的,但这可能是类的"可以被视为"关系。
啊,我不知道。
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*
- OpenCV C++:当垫子类型未知时无法访问垫子元素?
- 何时包含内置类型和运算符的标头?
- 基本类型与内置类型有什么区别C++
- 指内置类型的文字
- C++ 成员不是变量,而只是数据类型的名称吗?
- GLUT 问题:重新声明 c++ 内置类型'wchar_t'时出错
- 像自定义类一样构造的指针(内置类型)如何工作?
- 内置类型与用户定义的类型 C++
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- C++内置类型的基于类型的调度
- 函数重载:内置类型与用户定义类型
- 使用字符串而不是类型进行模板化
- 内置类型的构造函数初始化
- 内置类型的运算符函数
- 内置类型的重载运算符
- 在C++中,如何销毁内置类型?
- 基类到派生模板类的强制转换指针,而不知道类型
- 当使用类型为"类&&"的变量作为参数时,为什么调用复制 ctor 而不是移动 ctor
- 为什么 std::is_base_of<T, T> 当 T 是类类型时为真,而当 T 是内置类型时为假?