`decltype(true ? std::declval<T1>() : std::declval<T2>())`工作原理及推导疑问
解析模板max中用恒为true的三元运算符推导返回类型的逻辑
核心原因:条件运算符的类型推导规则
C++的条件运算符(?:)有个关键特性:不管条件表达式的真假,它的结果类型是由两个分支表达式的类型共同决定的,编译器会计算出两个分支都能隐式转换到的公共兼容类型,而不是只看被选中的那个分支的类型。
你看到的true ? std::declval<T1>() : std::declval<T2>(),虽然条件恒为true,但编译器不会只取第一个分支的类型,而是会执行以下步骤:
- 分析两个分支的类型:这里是
T1&&(std::declval<T1>()的类型)和T2&&(std::declval<T2>()的类型) - 根据C++的隐式类型转换规则,找到两者的公共提升类型:比如
int和double的公共类型是double,int和long的公共类型是long - 整个三元表达式的类型就是这个公共类型的右值引用,再通过
std::decay_t去掉引用属性,得到最终的返回类型RT
针对你的例子:max(1, 2.5)
当调用max(1, 2.5)时:
T1是int,T2是double- 三元表达式的两个分支是
int&&和double&&,编译器会把int隐式转换为double(因为double精度更高,不会丢失信息) - 所以整个表达式的类型是
double&&,经过std::decay_t处理后,RT被推导为double - 函数返回时,
a(int类型的1)会被隐式转换为double,最终返回double类型的2.5,符合预期
为什么不直接用decltype(std::declval<T1>())?
如果直接把RT的默认值设为decltype(std::declval<T1>()),那当传入int和double时,RT会是int,返回b < a ? a : b时,double类型的b会被截断为int,丢失小数部分——这显然不是max函数该有的行为。而用三元运算符的方式,正好利用了C++内置的类型提升规则,自动得到能安全容纳两个输入类型的返回类型。
为什么用恒为true的条件?
其实这里用true还是false都不影响结果,因为条件运算符的类型推导和条件的真假无关。用true只是一种约定俗成的写法,目的是明确告诉读者:我们不需要执行任何分支,只是利用这个运算符的类型推导特性来获取两个类型的公共兼容类型。
内容的提问来源于stack exchange,提问作者myoldgrandpa
相关产品推荐
相关产品推荐

