2012-10-10 38 views
5

Xin lỗi vì câu hỏi phức tạp, nhưng về cơ bản ý tưởng rất đơn giản. Tôi có mẫu lớp variadic:Có thể định nghĩa một mẫu lớp C++ 11 variadic có tham số thẻ tín hiệu Variadic phụ thuộc vào tham số mẫu nguyên không?

template<class P1, class P2, class ... P3s> 
class A 
{ 
    ... 
}; 

Tôi muốn có trình tạo A-class lấy tham số mẫu nguyên N và khởi tạo lớp A có tham số N P3. Giống như:

template<class P1, class P2, class P3, int N> 
class GenA : /* somehow */ : public A<P1, P2, /* N times */ P3, P3, ...> 
{ 
    ... 
}; 

Vì vậy, việc sử dụng sẽ là:

// Generates A<Class1, Class2, Class3, Class3, Class3> 
GenA<Class1, Class2, Class3, 3> a; 

Tôi đã cố gắng làm điều đó với thời gian đệ quy biên dịch và chuyên môn hóa một phần

template <class P1, class P2, int N, class P3> 
class GenA : public GenA<P1, P2, N-1, P3, P3> 
{ 
    ... 
} 

template <class P1, class P2, int N, class ... P3s> 
class GenA<P1, P2, 0, P3s ...> : public A<P1, P2, P3s, ...> 
{ 
    ... 
} 

tuy nhiên C++ 11 không công nhận mẫu thứ hai là một chuyên môn hóa của cái đầu tiên (bởi vì nó, trên thực tế, khác nhau) và không bao giờ đến trường hợp cơ bản của đệ quy (nó ngừng phàn nàn về quá nhiều đệ quy). Bất kỳ ý tưởng?

Cảm ơn
Tunnuz

+0

Có vẻ khó làm mà không có chuyên môn về mẫu quá mức. –

+0

Sau khi bạn đã chọn một trong các câu trả lời, bạn có thể cung cấp điểm chuẩn của các giải pháp không? – pmr

Trả lời

5
template<class P1, class P2, class... P3s> 
class A {}; 

template<class... Ps> 
struct TypeList {}; 

template<class P1, class P2, class P3, unsigned N, class P> struct GenHelp; 

template<class P1, class P2, class P3, class... Ps> 
struct GenHelp<P1, P2, P3, 0, TypeList<Ps...> > 
{ 
    typedef A<P1, P2, Ps... > AType; 
}; 

template<class P1, class P2, class P3, unsigned N, class... Ps> 
struct GenHelp<P1, P2, P3, N, TypeList<Ps...> > : public GenHelp<P1, P2, P3, N-1, TypeList<P3, Ps...> > 
{}; 

template<class P1, class P2, class P3, unsigned N> 
class GenA : public GenHelp<P1, P2, P3, N, TypeList<> >::AType 
{}; 
+0

Rực rỡ! Tôi sẽ lấy nó vì nó tương tự như những gì tôi đang cố gắng làm. – tunnuz

5

Bạn có thể sử dụng lệnh biến thiên thông số template mẫu để làm điều này. Trong triển khai này, chúng tôi chỉ đơn giản bắt đầu với gói đối số gồm P1P3 và tiếp tục mở rộng nó. Cuối cùng, chúng tôi khởi tạo tham số mẫu mẫu tham số variadic với gói đối số đó.

template<class P1, class P2, class ... P3s> 
struct A {}; 

template<template<class... Args> class AT, typename P3, int N, 
     typename... Already> 
struct GenAImpl { 
    typedef typename GenAImpl<AT, P3, N - 1, Already..., P3>::type type; 
}; 

template<template<class... Args> class AT, typename P3, 
     typename... Already> 
struct GenAImpl<AT, P3, 0, Already...> { 
    typedef AT<Already...> type; 
}; 


template<class P1, class P2, class P3, int N> 
struct GenA : GenAImpl<A, P3, N, P1, P2> 
{}; 

int main() 
{ 
    GenA<int, double, float, 3>::type X; 
    return 0; 
} 

Hãy nhớ rằng phụ thêm vào danh sách thường là một ý tưởng tồi (ít nhất là trong ngôn ngữ thực chức năng, tôi không có ý tưởng nếu đó thực sự tác động C++ hiệu suất biên dịch) và bạn đang tốt hơn với consing nó lại với nhau và đảo ngược nó ở cuối.

+0

Nhưng tôi sẽ upvote giải pháp này là tốt. – tunnuz

Các vấn đề liên quan