问题描述
在 GCC C++20 概念库中,它有
template<typename _Derived,typename _Base>
concept derived_from = __is_base_of(_Base,_Derived)
&& is_convertible_v<const volatile _Derived*,const volatile _Base*>;
- 为什么只需要
__is_base_of(_Base,_Derived)
还不够? - 测试中需要使用
const volatile
吗?
解决方法
std::derived_from
的行为是根据 unambiguous public inheritance
概念 derived_from<Derived,Base>
满足当且仅当
Base
是一个类类型,要么是 Derived
要么是公共和
Derived
的明确基数,忽略 cv 限定符。
请注意,当 std::is_base_of
时,此行为与 Base
不同
是 Derived
的私有或受保护的基础。
__is_base_of
是用于实现 std::is_base_of
的编译器内在函数。因此,单独使用它不会产生所需的行为。
因此,为了检查要求的“明确公共”部分,我们可以检查指向派生对象的指针是否可以隐式转换为指向基对象的指针。这只是 C++ 类的标准过程。如果类建模“is-a”关系、公共继承而不是来自多个基类,则指针是可转换的。
添加 const volatile
是为了处理“忽略 cv 限定符”的要求。通过始终添加它们,即使例如 _Derived
是 B const
到某个 A
(非常量)_Base
,转换也是合法的。按原样比较指针会尝试将 B const*
转换为 A*
,并且会因丢弃 cv 限定符而失败。
- __is_base_of 是不够的,因为私有基仍然是基,特征检查(用 cppreference 的话):
概念 derived_from<Derived,Base>
满足当且仅当 Base 是派生类或派生类的公共和明确基类,忽略 cv 限定符强>.
请注意,当 Base 是 Derived 的私有或受保护基时,此行为与 std::is_base_of 不同。
-
const volatile
是必需的,因为特征应该忽略 cv 限定符。指向T
的指针隐式转换为指向const volatile T
的指针,而指向相反的指针则不是。