非类型参数的非Deduced上下文

Ash*_*tti 13 c++ variadic-templates c++11 c++14 c++17

我正在阅读C++模板(第2版),这是本书的一个片段:

template<typename... Ts, int N>
void f(double (&)[N+1], Ts... ps) {return;}
Run Code Online (Sandbox Code Playgroud)

书中指出上述声明是无用的,因为无法指定或推导出N.

我试图理解为什么像下面这样的错误:

double arr[2];
f<int, double, 1>(arr, 1, 2.0);
Run Code Online (Sandbox Code Playgroud)

当我编译上面的代码片段时,我得到的错误是没有匹配函数来调用f.

编译好了

template<typename... Ts, typename T> 

void func(T value){}; 
func(1); 
Run Code Online (Sandbox Code Playgroud)

即使我在参数包后面有一个额外的参数.

为什么我明确指定的模板参数与提供的参数不匹配?请帮我理解这个.

Nel*_*eal 14

无法推导N的事实与参数包无关.由于无法推导出N,因此无法编译.

template<int N>
void f(double (&)[N+1]) {}

int main() {
    double arr[2];
    f(arr);
}
Run Code Online (Sandbox Code Playgroud)

来自cppreference(非推断的上下文):

在下列情况下,用于组成P的类型,模板和非类型值不参与模板参数推导,而是使用在别处推导或显式指定的模板参数.如果模板参数仅在非推导的上下文中使用且未明确指定,则模板参数推断将失败.
[...]
3)非类型模板参数或数组绑定,其中子表达式引用模板参数

无法指定N的事实有不同的原因:标准表示您根本无法指定参数包之后放置的参数.

来自[temp.param]:

函数模板的模板参数包不能跟随另一个模板参数,除非该模板参数可以从 函数模板的参数类型列表中推导出来或者具有默认参数(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
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

(看到我从中得到报价的这个问题)

您的其他示例有效,因为T可以从参数中推断出来.

template<typename... Ts, typename T> 
void func(T value){}; 
func(1); // 1 is used to deduce T
Run Code Online (Sandbox Code Playgroud)