非类型参数的非推导上下文

时间:2018-12-15 07:52:43

标签: c++ c++11 c++14 c++17 variadic-templates

我正在阅读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); 

即使在参数包之后我还有一个附加参数。

为什么我指定的模板参数明显不匹配提供的参数?请帮助我理解这一点。

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