模板模板参数中省略带默认实参的模板参数是否合法?
C++20模板模板参数匹配的编译器一致性问题
先看问题中的代码示例:
#include <algorithm> #include <vector> template <template<typename> typename C, typename T> void sort(C<T>& c) { std::sort(c.begin(), c.end()); } void f() { std::vector vi = { 1, 2, 3, 4, 5 }; ::sort(vi); }
问题核心
std::vector是带有两个模板参数的容器(第二个参数Alloc有默认实参std::allocator<T>),但sort函数的模板模板参数C仅声明了一个模板参数。在C++20标准下,这段代码是否合法?GCC能编译通过,Clang报“no matching function to 'sort'”错误,哪个编译器符合标准?
标准规则解析
C++20对模板模板参数的匹配规则做了关键调整:
- 在C++17及更早版本中,模板模板参数的参数数量必须与目标模板的参数数量完全一致,哪怕目标模板的剩余参数有默认实参,也无法匹配。
- C++20引入了前缀匹配规则:如果模板模板参数的参数列表是目标模板参数列表的前缀,且目标模板中超出前缀的参数都带有默认实参,那么两者可以匹配。
对于std::vector来说,它的模板参数列表是<T, Alloc = std::allocator<T>>,sort的模板模板参数C是<T>,属于前者的前缀,且第二个参数有默认值,完全符合C++20的匹配要求。
结论
这段代码在C20标准下是合法的,GCC的编译行为符合C20标准,而Clang的报错是未正确实现该C++20特性导致的。
内容的提问来源于stack exchange,提问作者Masquue
相关产品推荐
相关产品推荐

