2015-08-27 44 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不是一種類型(即模板模板或值)更難以處理。