2015-09-12 12 views
8

Tôi đã học được một số thời gian trước đây rằng bạn có thể tạo mẫu với các tham số bằng không. Mặc dù không thể tạo chúng trực tiếp, bạn có thể sử dụng mẫu thành viênBạn có thể làm gì với các mẫu có tham số mẫu không?

template<typename ...T> 
struct Maker { 
    template<T...> 
    struct HasNParams { }; 
}; 

Maker<>::HasNParams<> hnp; 

Tôi tự hỏi liệu điều này có được thiết kế tốt và bạn có thể làm gì với những con thú này không. Bạn có thể vượt qua chúng dưới dạng đối số mẫu và tạo chuyên môn rõ ràng (tôi đoán kịch bản duy nhất dành cho trường hợp trống sau đó)?

+2

Câu hỏi là "bạn có thể làm gì với' SomeClassTemplate <> '?" Điều đó đánh tôi khá rộng. – Barry

+1

Để được chung? Bạn có thể làm gì với một 'vector' trống? – Jarod42

+0

@Barry bạn không thể tạo chúng trước C++ 11 và tôi chưa thấy các ứng dụng, cũng như các bài viết về chúng. Điều này làm cho tôi tự hỏi cho dù họ là một tai nạn mà bạn không nên sử dụng trong mã của bạn? Hoặc có sử dụng, và chúng là gì? –

Trả lời

4

Có nguy cơ phát âm rõ ràng, kết thúc thuyết minh đệ quy.

template<typename Arg, typename ...T> 
struct Maker : public Maker<T...> 
{ 
    template<T...> 
    struct HasNmin1Params { }; 
}; 

Vấn đề ở đây là danh sách đối số thực tế để Maker là không có sản phẩm nào, nhưng chúng tôi chỉ sử dụng đối số N-1 trong HasNminOneParams.

+1

Cảm ơn, bạn có thể làm ví dụ không? Tôi chưa thấy cái này. –

1

Hãy xem xét các lớp mẫu sau:

template <typename... > struct typelist { }; 

Đây là lập trình meta tương đương với một container. Và theo cách tương tự, hữu ích khi có một số trống vector hoặc map, sẽ hữu ích khi có một số trống rỗng typelist. Tức là, một cái gì đó thuộc loại typelist<>. Dưới đây là hai trường hợp sử dụng ví dụ cho một cấu trúc như vậy.

Nó có thể là điều kiện chấm dứt cho loại đệ quy:

void foo(typelist<>) { } 

template <typename T, typename... Ts> 
void foo(typelist<T, Ts...>) { 
    bar<T>(); 
    foo(typelist<Ts...>{}); 
} 

Nó có thể là một "trở lại" giá trị cho một metafunction, cho thấy một tình trạng thất bại.

template <typename F, typename T> 
struct filter_one 
: std::conditional_t<F::template apply<T>::value, 
        typelist<T>, 
        typelist<>> 
{ }; 

Đó là một helper chúng ta có thể sử dụng để viết một metafunction lọc typelist:

template <typename F, typename TL> 
struct filter; 

template <typename F, typename... Ts> 
struct filter<F, typelist<Ts...>> 
: concat_t<filter_one<F, Ts>...> 
{ }; 

Cả hai đó là những tính năng rất hữu ích của typelist<>, và đó mới chỉ là mẫu một lớp.

+0

Hmm, nhưng những gì bạn có có một bản mẫu với một gói tham số rỗng.Trong ví dụ của tôi, chúng ta có một khuôn mẫu không có gói tham số, nhưng chỉ đơn giản là 0 tham số, như trong 'template <> struct Foo {}', được tạo bởi ngữ nghĩa chứ không phải cú pháp (vì cú pháp được dành riêng cho chuyên môn hóa rõ ràng). Tôi không thể thấy làm thế nào tôi có thể chuyển ví dụ của bạn cho trường hợp của tôi. –

+0

@ JohannesSchaub-litb Bạn có hai gói tham số trong ví dụ của mình. 'T' là một gói các loại và một gói' T 'chưa được đặt tên. Nó vẫn còn trống gói instantiation. Bạn đang yêu cầu cụ thể về một gói giá trị rỗng, không có loại? – Barry

+0

tại sao gói thứ hai chưa được đặt tên là 'T'? Điều đó không có ý nghĩa với tôi, bạn có thể giải thích thêm về điều đó không? Với tôi nó chỉ là sự mở rộng của 'T' vào một danh sách tham số và trong trường hợp của tôi dẫn đến 0 tham số. –

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