2011-09-12 23 views
5

Cho một mẫu nhưlà trình diễn mẫu có thể đệ quy rõ ràng có thể?

template<int dim> class Point { ... }; 

mẫu này có thể được khởi tạo một cách rõ ràng như

template class Point<0>; 
template class Point<1>; 
template class Point<2>; 
template class Point<3>; 

thay vì instantiating mỗi mẫu riêng như trên, tôi muốn nhanh chóng chúng đệ quy với một cuộc gọi như

template class RecursiveInstantiate<Point, 3>; 

nơi RecursiveInstantiate<T, i> sẽ khởi tạo T<i>, T<i-1>, ..., T<0>. Có phải bằng cách nào đó có thể tạo ra một lớp học như vậy RecursiveInstantiate? Nếu không thể, bạn có biết cách làm điều đó với bộ tiền xử lý không?

Trong thực tế, tôi quan tâm đến việc khái quát hóa điều này cho các lớp có nhiều tham số mẫu như Node<int i1,int i2,int i3> cho tất cả kết hợp i1, i2, i3 trong {0,1,2,3}. Nhưng tôi hy vọng có thể tự mình thực hiện phần thứ hai này.

Bất kỳ lời khuyên nào, cũng là một giải thích tại sao không thể những gì tôi muốn đạt được được đánh giá cao.


Cập nhật: cảm ơn bạn đã bình luận cho đến nay. Bây giờ tôi thấy rõ hơn vấn đề thực sự ở đâu. Dòng

template class Point<3>; 

instantiates mẫu và xuất ký hiệu của nó vào tệp đối tượng. Một instantiation của mẫu

template class RecursiveInstantiate<Point, 3>; 

có thể nhanh chóng các lớp class Point<3>, class Point<2>, .... Rõ ràng đây chỉ xảy ra tại địa phương mặc dù. Các mẫu không được xuất sang tệp đối tượng. Có lẽ tôi sẽ phải tìm một giải pháp bằng cách sử dụng bộ tiền xử lý.

Như tôi thấy bây giờ tôi chưa đặt câu hỏi đủ chính xác ngay từ đầu, tôi đánh giá cao câu trả lời của bạn và câu trả lời được chọn là chính xác.

Lưu ý: Tôi đang thử trên linux với g ++/clang làm trình biên dịch.

Trả lời

8

Bạn có thể làm một chút lớp Instantiator:

template <unsigned int N> struct Instantiator 
{ 
    Point<N> p; 
    Instantiator<N-1> i; 
}; 

template <> struct Instantiator<0> 
{ 
    Point<0> p; 
}; 

Sau đó, chỉ cần thêm một instantiation rõ ràng: template struct Instantiator<81>;

Bạn có thể mở rộng ý tưởng này tự từ điển để bất kỳ số lượng các thông số không thể thiếu.


Như @Georg nói, chúng ta hãy làm cho nó chung chung:

template <template <unsigned int> class T, unsigned int N> struct Instantiator 
{ 
    T<N> t; 
    Instantiator<T, N-1> i; 
}; 

template <template <unsigned int> class T> struct Instantiator<T, 0> 
{ 
    T<0> t; 
}; 

template struct Instantiator<Point, 82>; 
+0

Làm cho nó 'mẫu struct I {T p; I ; }; ... '. Ngoài ra, việc sử dụng meta-algorithm & meta-functions sẽ tránh được các thông số mã hóa cứng (xem Boost.MPL làm gì). –

+0

@Georg: Tôi thích phong cách của bạn! –

+0

Giải pháp này trông rất đẹp, tôi thực sự thích giải pháp chung của bạn. Tôi vẫn phải đấu tranh để làm việc này. Cách tiếp cận biên dịch độc đáo, có, nhưng bằng cách nào đó các biểu tượng cho 'Point <0> 'không được xuất khẩu vào tệp đối tượng, đó là những gì mã' lớp mẫu điểm <0>; 'sẽ làm. Tôi sẽ phải điều tra thêm vào ngày mai. Tôi đang sử dụng g ++/clang trên Linux, nhưng tôi không chắc liệu điều này có dành riêng cho kiến ​​trúc của tôi hay không. –

4

Bạn có thể làm điều đó như thế này:

template<int dim> struct Point { 
    static const int val = dim; 
    Point<dim - 1> p; 
}; 

template<> struct Point<0> { ... }; 

Điều đó tạo ra một mẫu chuyên môn cho các mẫu tham số khi nó là 0 nên đệ quy dừng lại ở đó, và khi bạn thể hiện hóa một như thế này:

Point<4> 

Nó khởi tạo từ Point<4> xuống Point<0>. Sau đó, bạn có thể làm

Point<4>::val 

để truy cập giá trị của số cụ thể đó.

+3

Điều đó đòi hỏi sửa đổi và có kiểm soát đối với định nghĩa của 'Point', mặc dù. –

+0

@Krerek khái niệm có thể dễ dàng được mở rộng để được sử dụng mà không cần sửa đổi 'Point'. –

+0

Cách tiếp cận này không hiệu quả đối với tôi. Nếu tôi khởi tạo 'lớp mẫu 'điểm <4>;' thì chỉ các ký hiệu cho' Point <4>' được xuất vào tệp đối tượng, chứ không phải các ký hiệu khác, mặc dù thực sự đệ quy được thực thi đúng bởi trình biên dịch. –

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