当前位置: 首页 > article >正文

无用知识研究:对std::common_type以及问号表达式类型的理解

common_type的实现里,利用了问号表达式:ternary conditional operator (?:)

https://stackoverflow.com/questions/14328034/what-is-the-point-of-this-condition-found-in-the-implementation-of-stdcommon-t

std::common_type的部分实现:

template <class T, class U>
struct common_type<T, U> {
    typedef decltype(true ? declval<T>() : declval<U>()) type;
};

?:这个表达式,有类型两个属性。有以下知识点:

1、表达式的。是运行时的逻辑,这个大家都很熟悉。比如一个问号表达式true : 2 : 1.0。它有一个值,这个值是根据condition判断出来的(这个例子里是true)。咱们可以用auto val来接住该值,auto val = true : 2 : 1.0; 那么val的值就是2.0。(注意,为什么是2.0,看下面分解)

2、表达式的类型。是编译时获取的。也就是说true : 2 : 1.0作为一个整体,它有一个类型,系统会取其“共同”的类型。至于怎么提取的,是系统决定的。这个类型可以用decltype()在编译器来取,比如decltype(true : 2 : 1.0)。记住它是在编译期来确定的,而不是运行期来确定,所以它不管condition的。所以第一条里面,true : 2 : 1.0的值为什么是2.0呢,因为decltype对其分析的结果就是double。下面的写法,编译不成功:

auto x = true ? 1 : L"123";

编译错误:
error C2446: “:”: 没有从“const wchar_t *”到“int”的转换
note: 没有使该转换得以执行的上下文
error C3536: “x”: 初始化之前无法使用


为什么编译不成功呢,那是因为int和const wchar_t*是没有共同类型的。


using T = decltype(true? std::declval<int>() : std::declval<const wchar_t *>());
或者
using T = decltype(false ? std::declval<int>() : std::declval<const wchar_t *>());

结果都一样,编译错误:
error C2446: “:”: 没有从“const wchar_t *”到“_Ty1”的转换
1>        with
1>        [
1>            _Ty1=int
1>        ]
note: 没有使该转换得以执行的上下文
而以下的写法,表达式的类型均为double

输出double
using T = decltype(1 ? 1 : 1.0);
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

输出double
using T = decltype(0 ? 1 : 1.0);
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

输出double
using T = decltype(0 ? 1.0 : 1);
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

输出double
using T = decltype(true ? std::declval<int>() : std::declval<double>());
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

输出double
using T = decltype(false? std::declval<int>() : std::declval<double>());
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

再看自定义指针的例子: 

提取shit0*和shit1*的共同类型。
运行结果:struct shit0 * __ptr64

struct shit0
{};
struct shit1 : shit0
{};

void Test()
{

using T = decltype(true ? std::declval<shit0*>() : std::declval<shit1*>());
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

}

///
提取shit0和shit1的共同类型。
运行结果:struct shit0

struct shit0
{};
struct shit1 : shit0
{};

void Test()
{

using T = decltype(true ? std::declval<shit0*>() : std::declval<shit1*>());
std::cout << boost::typeindex::type_id_with_cvr<T>().pretty_name() << std::endl;

}

貌似等于号=也有类似属性,之后再研究吧


http://www.kler.cn/a/524514.html

相关文章:

  • C++中的类与对象(中)
  • 【最后203篇系列】007 使用APS搭建本地定时任务
  • 【C++ 真题】P1706 全排列问题
  • 大数据治理实战:架构、方法与最佳实践
  • Java面试题2025-并发编程进阶(线程池和并发容器类)
  • 团体程序设计天梯赛-练习集——L1-022 奇偶分家
  • 论文阅读笔记:MambaOut: Do We Really Need Mamba for Vision?
  • Unity游戏(Assault空对地打击)开发(2) 基础场景布置
  • 对顾客行为的数据分析:融入2+1链动模式、AI智能名片与S2B2C商城小程序的新视角
  • printf和sprintf区别
  • 深入MapReduce——从MRv1到Yarn
  • fscan全家桶更新:fscan免杀版,可过360、火绒、微步云沙箱,其他的自行测试
  • Elasticsearch的开发工具(Dev Tools)
  • 创建实用PPT演讲者备注的有效方法
  • AI赋能医疗:智慧医疗系统源码与互联网医院APP的核心技术剖析
  • FreeRTOS的任务创建和删除
  • C#语言的并发编程
  • STM32 TIM输入捕获 测量频率
  • F1. Omsk Metro (simple version)
  • 微信小程序高级开发(5):微信小程序手机验证码登录全栈开发指南
  • Node.js 中文编码问题全解析
  • 【deepseek】deepseek-r1本地部署-第三步:下载模型
  • CISCO路由基础全集
  • Unity 粒子特效在UI中使用裁剪效果
  • Hugging Face挑战DeepSeek,AI开源竞赛升级!
  • Haskell语言的安全开发