C++ 将模板参数包从一个可变参数模板传递到另一个模板会导致编译器错误

标签 c++ templates variadic

<分区>

以下代码会导致编译器错误,但仅适用于 gcc(最高 5.2)和 clang(最高 3.7)。 VS2015 编译没有问题。 (对于 g++,您必须使用选项 -std=c++14)

//************************************************
template <int... items>
struct Sequence {
//************************************************
public:
  enum { size = sizeof...(items) };
  operator int() const { return data[rank - 1]; }
  Sequence& operator=(const Sequence& s) { rank = s.rank; return *this; }
  int get_rank() const { return rank; }
  bool first() { rank = 1; return true; }
  bool last() { rank = size; return true; }
  bool next() { return (rank < size) ? ++rank, true : false; }
  bool prev() { return (rank > 1) ? --rank, true : false; }
  bool is_first() { return rank == 1; }
  bool is_last() { return rank == size; }
protected:
  static const int data[sizeof... (items)];
  int rank = 1;
};

template <int... items> 
const int Sequence<items...>::data[sizeof...(items)] = { items... };


//************************************************
template <unsigned N, template <unsigned> class F, int... items> 
struct generate_sequence {
//************************************************
  typedef typename generate_sequence<N - 1, F, F<N>::value, items...>::result result;
};

//************************************************
template <template <unsigned> class F, int... items> 
struct generate_sequence<0, F, items...> {
//************************************************
  typedef Sequence<F<0>::value, items...> result;
};


//************************************************
template <int... coeffs>
struct polynomial {
//************************************************
  template <int var, int a0, int... ai> struct ipoly { enum { value = a0 + var * ipoly<var, ai...>::value }; };
  template <int var, int a0> struct ipoly<var, a0> { enum { value = a0 + 0 * var }; };

  template <unsigned index>
  class number_generator { public: enum { value = ipoly<index + 1, coeffs...>::value }; };
};


//************************************************
template <unsigned N>
class NaturalNumbers : public generate_sequence<N - 1, polynomial<0,1>::number_generator>::result {};
//************************************************

//************************************************
template <unsigned N, int... coeffs>
class PolynomialNumbers : public generate_sequence<N - 1, polynomial<coeffs...>::number_generator>::result {};
//************************************************

int main() {
  NaturalNumbers<10> nn;
  PolynomialNumbers<10,0,1> pn;
}

编译器输出如下:

bug.cpp:59:98: error: type/value mismatch at argument 2 in template parameter list for 'template<unsigned int N, template<unsigned int <anonymous> > class F, int ...items> struct generate_sequence'
 class PolynomialNumbers : public generate_sequence<N - 1, polynomial<coeffs...>::number_generator>::result {};
                                                                                                  ^
bug.cpp:59:98: note:   expected a class template, got 'polynomial<coeffs ...>::number_generator'
bug.cpp:59:101: error: expected '{' before 'result'
 class PolynomialNumbers : public generate_sequence<N - 1, polynomial<coeffs...>::number_generator>::result {};
                                                                                                     ^
bug.cpp: In function 'int main()':
bug.cpp:64:27: error: non-template type 'PolynomialNumbers' used as a template
   PolynomialNumbers<10,0,1> pn;
                           ^

这是编译器错误还是代码有问题?对我来说关键在于行

expected a class template, got 'polynomial::number_generator'

编译器输出。编译器显然没有意识到“polynomial::number_generator”实际上是一个模板。什么意思?

最佳答案

由于 number_generator 是一个从属 名称,您必须在它前面加上 template 关键字:

template <unsigned N, int... coeffs>
class PolynomialNumbers 
: public generate_sequence<
      N - 1, 
      polynomial<coeffs...>::template number_generator
                          // ^^^^^^^^
      >::result 
{};

作为旁注,最好避免在任何地方传递模板模板并尝试重写您的 number_generator 使其更像一个元函数类:

class number_generator {
public: 
    template <unsigned index>
    using apply = ipoly<index + 1, coeffs...>;
};

这将使您的所有代码更容易,因为类型是一等公民,任何不是类型的东西(即模板模板或值)都更难处理。

关于C++ 将模板参数包从一个可变参数模板传递到另一个模板会导致编译器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32259728/

相关文章:

opencv - 确定数据类型并用作模板类型名

c++ - 不同非类型模板参数的不同成员函数

c++ - Valgrind 条件跳转或移动取决于使用可变参数函数的链式调用时未初始化的值

c++ - 重复使用可变参数函数参数不起作用

c++ - 通过构造函数插入 std::map

c++ - 使用 SetData() 分配数据后 cvReleaseImage() 出现段错误

c++ - 简单的 C++ 递归不能正常工作——我只是不明白为什么

c++ - STL 的 set 的 insert 方法是否复制传递对象的值?

c++ - 派生可变参数类模板的调用函数模板重载

c - 可变参数宏 - 省略号前的逗号?