C++20标准中为何模板场景下std::basic_string转basic_string_view隐式转换失败
C++20中模板场景下string到string_view隐式转换失效的规则依据
前置说明
首先明确三个关键定义:
std::string是std::basic_string<char, std::char_traits<char>, std::allocator<char>>的别名std::string_view是std::basic_string_view<char, std::char_traits<char>>的别名std::basic_string提供了成员转换运算符:operator std::basic_string_view<CharT, Traits>() const noexcept,允许将字符串对象转换为对应类型的字符串视图
非模板场景的正常转换
当使用非模板函数接收std::string_view时,std::string可以通过上述转换运算符完成隐式转换,代码可正常编译:
#include <iostream> #include <string> #include <string_view> void foo(std::string_view v){ std::cout<<"ok"; } int main(){ foo(std::string{"abc"}); }
模板场景的转换失效问题
但如果将函数抽象为模板,隐式转换会直接失效:
#include <iostream> #include <string> #include <string_view> template<class CharT, class Traits> void foo(std::basic_string_view<CharT, Traits> v){ std::cout<<"ok"; } int main(){ foo(std::basic_string<char>{"abc"}); }
规则依据(C++20)
这个现象的核心原因来自C++20标准中模板实参推导的规则(对应标准章节 [temp.deduct.call]):
在模板函数的实参推导阶段,编译器只会考虑标准转换序列以及用户定义转换序列的起始标准转换步骤,不会执行完整的用户定义转换来推导模板参数。
具体到这个场景:
当调用模板foo时,编译器需要推导CharT和Traits两个模板参数。传入的实参是std::basic_string<char>,而形参是std::basic_string_view<CharT, Traits>——这两个类型之间没有直接的标准转换关系,必须通过std::basic_string的用户定义转换运算符才能完成类型转换。但模板推导阶段不会触发这个用户定义转换,因此编译器无法推导出CharT和Traits的正确取值,最终导致编译失败。
内容的提问来源于stack exchange,提问作者PavelDev
相关产品推荐
相关产品推荐

