为何std::string不提供直接接收std::string_view参数的构造函数
核心原因是避免破坏C++17之前的既有代码,防止出现重载决议二义性
如果直接添加接收std::basic_string_view的普通构造函数,会和已有的C风格字符串构造函数产生歧义,我们可以看最典型的场景:
// 假设std::string提供了普通的string_view构造函数 std::string s("hello world");
字符串字面量"hello world"的类型是const char[12],它同时支持两种同优先级的隐式转换:
- 转换为
const char*,匹配std::string原生的C风格字符串构造函数 - 转换为
std::string_view,匹配新添加的string_view构造函数
重载决议无法判断这两个构造函数的优先级,会直接报二义性错误,导致所有用字符串字面量构造std::string的已有代码全部编译失败,属于完全不可接受的兼容性问题。
为什么模板构造函数可以规避歧义
标准采用的模板构造函数带约束(C++20前用SFINAE实现),仅当入参可以转换为std::basic_string_view时才会生效,而模板参数推导的规则让它的匹配优先级低于原生的精确匹配构造函数:
当传入字符串字面量时,const char*构造函数是精确匹配,优先级高于需要做隐式转换的模板构造函数,因此会直接走原生构造逻辑,不会触发二义性。
只有当入参本身就是std::basic_string_view类型,或者没有更优的原生构造函数匹配时,才会走这个模板构造函数的逻辑。
为什么需要额外的推导指引
因为这个模板构造函数的模板参数仅包含入参类型T,没有包含std::basic_string自身的CharT、Traits模板参数信息,当使用C++17引入的类模板实参推导(CTAD)语法时,编译器没法从std::basic_string_view入参推导出std::basic_string的模板参数,因此需要额外添加专门的推导指引来补全这个场景的推导规则。
内容的提问来源于stack exchange,提问作者oliora
相关产品推荐
相关产品推荐

