为何仅传入一个模板参数实例化std::basic_string_view不会触发模板参数不足的编译错误?
为何仅传入一个模板参数实例化std::basic_string_view不会触发模板参数不足的编译错误?
这个问题抓得真准!你发现的现象确实有点反直觉——明明在MSVC标准库和libc++的实现里,std::basic_string_view的类模板定义看起来是这样的(第二个模板参数_Traits没加默认值):
template <class _Char, class _Traits> class basic_string_view { // ... 库内部实现代码 };
但你只传一个char作为模板参数去实例化它,编译器却完全不报错,这到底是咋回事?
其实秘密藏在你没注意到的头文件细节里!根据C++标准的强制要求,std::basic_string_view的第二个模板参数必须带有默认值std::char_traits<_CharT>。所以这些库的实现中,早在类模板的第一次声明(通常是头文件里的前置声明)时,就已经指定了这个默认参数,比如:
// 在<string_view>头文件的某个位置,你可能没留意到的声明 template <class _CharT, class _Traits = std::char_traits<_CharT>> class basic_string_view;
而C++的规则是:类模板的默认参数只需要在第一次出现的声明里指定就行,后续的类模板定义(或者重复声明)可以选择省略这些默认参数。所以你看到的定义里没写默认参数,但编译器已经从之前的声明中知道了_Traits的默认值是什么,实例化时会自动把第二个参数补成std::char_traits<char>,自然就不会报“模板参数不足”的错误了。
对比libstdc的实现,它是在类模板定义里直接写了默认参数,看起来更直观,但本质上和MSVC、libc的实现完全一致——都是严格遵守C++标准的要求,确保我们可以像std::basic_string_view<char>这样简洁地实例化它(毕竟std::string_view本身就是这个实例的别名嘛)。
内容来源于stack exchange
相关产品推荐
相关产品推荐

