对递归模板类定义的基本案例的要求

时间:2017-02-19 16:15:17

标签: c++ class recursion template-specialization

对于我问here的问题,我得到了使用这样的一般模式来解决我的问题的建议:

template <class... T>
class C;

template <>
class C<>
{
public:
    void f() {}
};

template <class T, class... Args>
class C<T, Args...> : public C<Args...>
{
public:
    using C<Args...>::f;
    void f(const T& t) { /*stuff*/ }
};

现在,我不完全理解为什么这种模式必须像这样,所以我试图通过一个关于它是如何工作的假设来调整它。在改编中,我想在一个带有1而不是0模板参数的基本情况下结束递归,所以我按如下方式更改了代码片段:

template <class V, class... >
class C;

template <class V>
class C
{
public:
    void f() {}
};

template <class V, class T, class... Args>
class C<V, T, Args...> : public C<V, Args...>
{
public:
    using C<Args...>::f;
    void f(const T& t) { /*stuff*/ }
};

这里V应该继续传递,直到Args...为空,然后

template <class V>
class C
{
public:
    void f() {}
};
应该选择

。但是这会引发错误:

error: too few template parameters in template redeclaration
template <class V>
^~~~~~~~~~~~~~~~~~

note: previous template declaration is here
template <class V, class... >
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

所以我的假设是错误的。这实际上是如何工作的,以及我的适应性的正确变化需要是什么?

2 个答案:

答案 0 :(得分:1)

你忘记了该法术的专业化:

template <class V>
class C<V>
//    ^^^^  you missed this

答案 1 :(得分:1)

这里有两个错误: 首先,不正确的专业化:

struct S
{
  static constexpr int a[5] = {0};
};


int main()
{
  S s{};
  [[gnu::unused]] int b = s.a[0]; // force S stuff to be emitted
  return 0;
}

应该是:

template <class V>
class C
{
    //...
};

其次,template <class V> class C<V> { //... }; 声明不正确:

using

应该是:

using C<Args...>::f;