You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

技术问询:std::is_convertible是协变还是逆变?

嘿,咱们来拆解一下std::is_convertible在基类和派生类指针场景下的行为,基于标准定义的逻辑来分析:

关于std::is_convertible与类指针转换的细节

首先,根据C++标准的定义,std::is_convertible<From, To>的判定逻辑等价于检查下面这个虚构的测试函数是否是良构的(可以简单理解为能否通过编译):

template<class From, class To>
auto test(int) -> decltype(static_cast<To>(std::declval<From>()), std::true_type{});
template<class, class>
auto test(...) -> std::false_type;

using result = decltype(test<From, To>(0));

核心就是判断:从From类型的表达式能否隐式转换为To类型。

接下来针对Base和Derived(假设Derived是Base的公有派生类)的指针类型逐一分析:

1. test<Derived*, Base*>()的结果

当模板参数是From=Derived*、To=Base*时:

  • C++允许派生类指针隐式向上转型为基类指针,这是安全的(因为Derived对象包含Base的所有成员)。
  • 所以这个虚构的test函数可以正常编译,对应的std::is_convertible<Derived*, Base*>::value会是true。

2. test<Base*, Derived*>()的结果

当模板参数是From=Base*、To=Derived*时:

  • 基类指针不能直接隐式向下转型为派生类指针——因为Base指针可能指向的是一个纯Base对象,而非Derived对象,这种转换是不安全的,C++不会允许隐式进行。
  • 此时第一个test重载会因为无法完成隐式转换而不被匹配,编译器会选择参数为...的重载,因此std::is_convertible<Base*, Derived*>::value会是false。

这里需要澄清一个小误区:你提到的“若To与From协变(即当From是To的基类时),std::is_convertible<From, To>::value应求值为true”表述有点偏差。正确的协变转换方向是派生类→基类,也就是当To是From的基类时,std::is_convertible<From, To>才会返回true,反过来的基类到派生类是不满足隐式转换条件的。

内容的提问来源于stack exchange,提问作者Alexander Bily

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:38:54