请看下面的代码,显然GCC和Clang都很高兴接受:[coliru]:
template <class ... P1, class T1, class ... P2, class T2, class ... P3>
constexpr int f(T1, T2) {
return sizeof...(P1) + sizeof...(P2) + sizeof...(P3);
}
int main() {
static_assert(f(12, 3.4) == 0);
}
为什么要编译?标准中是否有一条规则规定,当无法推导模板参数包时,假定它为空?
答案 0 :(得分:1)
[temp.param] 17.1 / 15打算根据示例使您的代码格式错误:
// U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error
但是文字有点不清楚:
如果类模板,变量模板或别名模板的模板参数具有默认模板, 参数,随后的每个template-parameter必须提供一个默认template-argument或为 模板参数包。如果是主要类别范本,主要变数范本或 别名模板是模板参数包,它应该是最后一个模板参数。模板参数 一组功能模板之后不应再有另一个模板参数,除非该模板 参数可以从功能模板的parameter-type-list(11.3.5)推导出,也可以使用默认值 论点(17.9.2)。演绎指南模板(17.10)的模板参数没有默认值 参数可以从推导指南模板的parameter-type-list中推导。
问题是模板参数包不是模板参数;尽管T..., U...
禁止用于模板类,但将其从模板函数中阻止的措辞似乎有点错误。
您还可以争辩说,将类型传递给这些包的可能性不大:
该程序格式错误,如果出现以下情况,则无需进行诊断: [...] 可变参数模板的每个有效专业化都需要一个空的模板参数包,
但这是一个严重的延误。