2011-01-16 42 views
15

Tiếp tục my journey into the world of variadic templates, tôi gặp phải sự cố khác.Chuyên môn mẫu từng phần với nhiều gói thông số mẫu

Giả sử các lớp mẫu sau:

template < typename T > 
struct foo 
{ 
    //default implementation 
}; 

nó có thể một phần chuyên nó cho variadic mẫu instantiations như thế này:

template < template < typename ... > class T, typename ...Args > 
struct foo< T<Args...> > 
{ 
    //specialized implementation 
}; 

Với điều này, foo<int> sẽ tương ứng với việc thực hiện mặc định và foo< std::tuple< int, char > > thực hiện chuyên ngành.

Tuy nhiên, mọi thứ trở nên phức tạp hơn khi sử dụng một số thông số mẫu. Ví dụ, nếu chúng ta có các lớp mẫu sau

template < typename T, typename U > 
struct bar {}; 

và chúng tôi muốn một phần chuyên nó như chúng tôi đã làm cho foo, chúng ta không thể làm

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > {}; 

//This would correspond to the specialized version with 
//T=std::tuple, 
//TArgs=int,char 
//U=std::tuple, 
//UArgs=float 
bar< std::tuple< int, char >, std::tuple<float> > b; 

Thật vậy, nếu tôi đúng, chúng tôi chỉ có thể có một gói tham số mẫu và nó phải được đặt ở cuối danh sách tham số. Tôi hiểu tại sao điều này là bắt buộc trong các khai báo mẫu, nhưng đối với một số chuyên môn mẫu từng phần nhất định (như ví dụ trên), đây không phải là vấn đề.

Có thể đạt được chuyên môn mẫu từng phần với nhiều gói thông số mẫu không?


Sửa: Bây giờ tôi cảm thấy ngớ ngẩn ... mã tôi đã ở trên biên dịch một cách hoàn hảo (ít nhất là với gcc 4.5). Lỗi biên dịch mà tôi đã có không phải do nhiều gói tham số, mà là vì chúng sử dụng như các tham số hàm thành viên. Trong chuyên môn hóa từng phần của bar, tôi đã cố gắng để xác định một hàm thành viên đó phải mất cả TArgsUArgs thông số:

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > 
{ 
    void method(TArgs... targs, UArgs... uargs) //compile error here 
    { 
    } 
}; 

Trên khai báo hàm thành viên, gcc mang lại cho tôi những lỗi

thông số gói phải ở cuối danh sách tham số.

Theo như tôi có thể biết, trình biên dịch sẽ có thể xác định hàm thành viên chính xác cho một bản mẫu đã cho, ví dụ: bar< std::tuple< int, char >, std::tuple<float> > phải chứa hàm thành viên void method(int, char, float). Tôi có làm điều gì sai? Hay tôi đang cố gắng làm điều gì đó không thể? Nếu vậy, có lý do chính đáng tại sao điều này là không thể?

+0

Gọn gàng, tôi không biết bạn có thể chuyên/chỉ định (một phần) các thành phần của danh sách mẫu làm bản thân mẫu. – JAB

Trả lời

6

Có lẽ câu trả lời này sẽ không xóa câu hỏi của bạn trực tiếp, nhưng mã sau được biên dịch trên ideone (gcc-4.5.1) khi tôi kiểm tra.

#include <cstdio> 
#include <tuple> 

template< class, class > struct S { 
    S() { puts("primary"); } 
}; 

template< 
    template<class...> class T, class...TArgs 
, template<class...> class U, class...UArgs 
> 
struct S< T<TArgs...>, U<UArgs...> > { 
    S() { puts("specialized"); } 
}; 

int main() 
{ 
    S< int, int > p;          // "primary" 
    S< std::tuple< int, char >, std::tuple<float> > s; // "specialised" 
} 

Tôi không chắc chắn mã này là nghiêm chỉnh tuân thủ QTI, nhưng như xa như tôi đọc N3225 14.5.3, tôi không thể tìm thấy những tuyên bố đó đề cập đến rằng gói mẫu tham số đã được các mẫu mới nhất tham số.

Edit:
Tôi đọc lại N3225 và tìm thấy những điều khoản sau đây:

8.3.5/4 Nếu tham số-khai-khoản chấm dứt với một dấu chấm lửng hoặc một chức năng gói tham số (14.5.3), số đối số phải bằng hoặc lớn hơn số tham số không có đối số mặc định và không hoạt động gói tham số.

14.8.2.5/10 [Lưu ý: Gói tham số chức năng chỉ có thể xảy ra ở số cuối danh sách khai báo tham số (8.3.5). -end note]

Vì vậy, như bạn đã đề cập, gói thông số chức năng đã được các tham số cuối cùng không may.
Chức năng thành viên không phải mẫu của mẫu lớp là một hàm bình thường cho lớp đó khi nó được khởi tạo (hoàn toàn chuyên biệt). Vì vậy, tôi muốn rằng mã trong câu hỏi này có thể được biên dịch một cách logic, như một trường hợp đặc biệt .

+0

Bạn nói đúng, mã biên dịch hoàn hảo! Vấn đề tôi thêm vào thực ra hơi khác một chút, tôi sẽ chỉnh sửa câu hỏi ... Xin lỗi vì sự bất tiện này ... –

+0

@LucTouraille: Đừng lo :-) Đây là dịp tự học tốt cho tôi. –

+0

Điều gì đó khiến tôi hiểu rằng báo giá không có ý định áp dụng ở đây vì cả hai gói tham số đã được biết và chỉ cần được mở rộng. nó sẽ không làm tôi ngạc nhiên nếu clang sẽ chấp nhận mã này –

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