【问题标题】:Non Deduced context for a non type parameter非类型参数的非推导上下文
【发布时间】:2019-05-16 08:44:39
【问题描述】:

我正在阅读 C++ 模板(第 2 版),这是本书中的一个 sn-p:

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);

当我编译上面的 sn-p 时,我得到一个错误,即没有匹配的函数来调用 f。

这编译得很好

template<typename... Ts, typename T> 

void func(T value){}; 
func(1); 

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

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

【问题讨论】:

  • @πάντα ῥεῖ - 嗯......这编译得很好 - 模板 void func(T value){};函数(1);即使我在参数包之后还有一个附加参数。再一次,我在这里的问题与您所链接的问题不同,因为我不是要求编译器进行演绎,而是帮助它进行演绎。需要了解为什么会失败。
  • Clang 给出此通知“候选模板被忽略:模板参数 'Ts' 的显式指定参数无效”。调用f&lt;int, double&gt;(arr, 1, 2.0) 编译成功! f(arr, 1, 2.0) 也是如此。所以看来N可以推断出来,至少在g++和clang++中是这样。
  • @CygnusX1....对不起我的错...我已经编辑了这个问题....它实际上是 N+1 而不是 N....

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


【解决方案1】:

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

【讨论】:

  • 非常感谢 Nelfeal。这完美地回答了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 2011-10-07
  • 1970-01-01
  • 2020-07-15
  • 2016-12-30
  • 1970-01-01
  • 2022-12-22
相关资源
最近更新 更多