2015-08-27 46 views
0

以下代码会导致编译器错误,但仅针对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; 
         ^

这是编译器故障或是代码不知何故错误?对我来说,关键在于行

预期类模板,得到了“多项式:: number_generator”

编译器输出的

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

回答

1

由于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...>; 
}; 

这会让所有的代码更容易,因为类型是一等公民和任何次at不是一种类型(即模板模板或值)更难以处理。