我正在阅读C ++模板(第二版),这是该书的摘录:
template<typename... Ts, int N>
void f(double (&)[N+1], Ts... ps) {return;}
书中指出,上述声明是无用的,因为无法指定或推导N。
我试图理解为什么类似以下内容的错误:
double arr[2];
f<int, double, 1>(arr, 1, 2.0);
当我编译上面的代码片段时,我得到一个错误,即没有匹配的函数可以调用f。
这样可以编译
template<typename... Ts, typename T>
void func(T value){};
func(1);
即使在参数包之后我还有一个附加参数。
为什么我指定的模板参数明显不匹配提供的参数?请帮助我理解这一点。
答案 0 :(得分:14)
不能推导出N的事实与参数包无关。这也不会编译,因为无法推导N。
template<int N>
void f(double (&)[N+1]) {}
int main() {
double arr[2];
f(arr);
}
来自cppreference(非推论上下文):
在以下情况下,用于构成P的类型,模板和非类型值不参与模板自变量的推导,而是使用在其他地方推导或明确指定的模板自变量。如果模板参数仅在未推导的上下文中使用且未明确指定,则模板参数推导将失败。
[...]
3)非类型模板参数或数组绑定,其中子表达式引用模板参数
无法指定N的事实有不同的原因:标准指出,您根本无法指定放置在参数包之后的参数。
来自[temp.param]:
不得遵循功能模板的模板参数包 除非可以从 parameter-type-list 推导出该模板参数,否则使用另一个模板参数 函数模板的名称或具有默认参数(14.8.2)。 [示例:
template<class T1 = int, class T2> class B; // error // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error template<class... T, class U> void g() { } // error
-结束示例]
(请参阅this question,我从中获得了报价)
您的其他示例可行,因为可以从参数推导T
。
template<typename... Ts, typename T>
void func(T value){};
func(1); // 1 is used to deduce T