模板推导和显式提供的参数包类型

时间:2018-03-16 11:20:17

标签: c++ templates variadic-functions pack template-deduction

我会简化和缩短这个问题以便于回答。

必要的是:

为什么要编译和执行此代码

  # include <iostream>
  template <class A> class Goofy {};

  template <int N, template <class> class B, class A, int ... K, class ... Z>
  void f ( A a, B<A> b, Z ... z )
  {
   std::cout << "I'm executed" << std::endl;
  }

  int main()
  {
   Goofy<int> goofy;
   f<1, Goofy, int, 2, 3, 4>(2,goofy,1.3,'a',1.f);
   }

而以下不是?

  # include <iostream>
  template <class A> class Goofy {};

  template <int N, template <class> class B, class A, int ... K, class ... Z>
  void f ( A a, B<A> b, Z ... z )
  {
   std::cout << "I'm executed" << std::endl;
  }

  int main()
  {
   Goofy<int> goofy;
   f<1, Goofy, int, 2, 3, 4, double, char, float>(2,goofy,1.3,'a',1.f);
   }

唯一的区别是类型的显式和一致供应 实例化包Z

我不认为这会以编译错误结束,而且还会 ,恕我直言,诊断告诉模板扣除/替换失败 没有必要扣除。

有人可以向我解释一下吗?

我使用编译器GNU 7.3.1和 clang 4.0.1并且两者都表现相同,所以我担心我的推理中存在严重错误......但我找不到。

1 个答案:

答案 0 :(得分:3)

您的代码可以缩减为:

template <int... N, class T>
auto foo(T) {};

auto test()
{
    foo<1, 2, 3>(4); // OK
    foo<1, 2, 3, int>(4); // ERROR
}

原因是可变参数是贪婪的。这就是为什么他们在明确说明它们时需要最后的原因。

撰写foo<1, 2, 3>(4);时:

  • 1, 2, 3int... N匹配 - &gt; N推断为1, 2, 3 - &gt;确定
  • 然后T从函数参数推导出来,即4int - &gt;行

撰写foo<1, 2, 3, int>(4);时:

  • 1, 2, 3, intint... N匹配 - &gt;错误