三元运算符作用于const char* const&与char*&的返回类型及编译器分歧咨询
三元运算符作用于
const char* const&和char*&的返回类型解析 问题现象
给定以下代码:
#include <type_traits> char* dummy; const char* const& a = dummy; char* & b = dummy; using T = decltype(true ? a : b); static_assert(std::is_same<const char* const&, T>::value); // Clang、MSVC(C++20) 通过 static_assert(std::is_same<const char* , T>::value); // GCC、MSVC(C++17) 通过
不同编译器的行为存在分歧:
- GCC 在所有C++版本中判定
T为const char* - Clang 在所有C++版本中判定
T为const char* const& - MSVC 在C17模式下返回
const char*,C20模式下返回const char* const&
标准规则解析
分歧的根源在于C17与C20对条件表达式(三元运算符)的类型推导规则差异:
C++17及更早版本
根据C++17标准的[expr.cond]条款:
- 首先剥离两个操作数的引用属性,得到底层类型:
a的表达式类型为const char* const(左值),b的表达式类型为char*(左值)。 - 推导两者的公共类型为
const char*——char*可隐式转换为const char*,而const char* const的顶层const会被忽略在类型转换中。 - 由于公共类型
const char*并非引用类型,条件表达式会将两个操作数转换为该类型的纯右值(prvalue),最终decltype推导的结果为值类型const char*。
C++20及更新版本
C++20对条件表达式的规则做了优化,当两个操作数均为左值,且其中一个可隐式转换为另一个的类型时:
char*可隐式转换为const char* const(先转换为const char*,再添加顶层const),此时条件表达式无需创建临时对象,直接返回左值引用类型const char* const&。- 因此
decltype推导的结果为引用类型const char* const&。
结论
- 在C++17及更早版本,符合标准的返回类型是
const char*,GCC和MSVC(C++17)的行为正确。 - 在C++20及更新版本,符合标准的返回类型是
const char* const&,Clang和MSVC(C++20)的行为正确。
内容的提问来源于stack exchange,提问作者康桓瑋
相关产品推荐
相关产品推荐

