2011-12-29 37 views
5

Tôi đã chơi với các tham số mẫu variadic bằng gcc 4.6.1. Các mã sau biên dịch như mong đợi:Loại chức năng trong mẫu không biên dịch

template<typename RetType, typename... ArgTypes> 
class Event; 

template<typename RetType, typename... ArgTypes> 
class Event<RetType(ArgTypes...)> 
{ 
public: 
    typedef function<RetType(ArgTypes...)> CallbackType; 

    void emit(ArgTypes...args) 
    { 
     for (CallbackType callback : callbacks) 
     { 
      callback(args...); 
     } 
    } 

private: 
    vector<CallbackType> callbacks; 
}; 

Nhưng để ngạc nhiên của tôi phiên bản sau "bình thường" mà chỉ có một "Loại Đối số" không biên dịch:

template<typename RetType, typename ArgType> 
class Event; 

template<typename RetType, typename ArgType> 
class Event<RetType(ArgType)> // <- error: wrong number of template arguments (1, should be 2) 
{}; 

g ++ 4.6.1 cho lỗi như trong bình luận.

Bất kỳ ai biết tại sao nó gây ra lỗi và cách làm cho nó hoạt động? Ngoài ra, tôi có đúng trong suy nghĩ mã trên là một hình thức "mẫu chuyên môn hóa một phần"?

Trả lời

4
template<typename RetType, typename ArgType> 
class Event; 

hy vọng 2 đối số mẫu, RetTypeArgType, bạn chỉ cung cấp cho nó một RetType(ArgType).

template<typename RetType, typename... ArgType> 
class Event; 

hy vọng 1 hoặc nhiều đối số mẫu, RetTypetùy chọnArgType s.

+0

Dường như trình biên dịch nghĩ RetType (ArgType) là một đối số thay vì khai báo kiểu hàm mà tôi muốn nói. Tự hỏi tại sao nó không thể đối xử với nó theo cách giống như tuyên bố variadic. Và không, nó không phải đệ quy. Sự tăng cường của tôi về việc sử dụng các đối số variadic ở đây là chuyển tiếp khai báo kiểu hàm và sử dụng các đối tượng hàm. –

+0

Kos: Không phải. Đã xóa nhận xét đó. – ronag

+0

H Xu: Tôi không nghĩ phiên bản variadic hoạt động như bạn mong đợi. Tôi nghĩ rằng ArgTypes ... sẽ luôn luôn trống rỗng theo cách bạn đang sử dụng nó. – ronag

1

Tôi nghĩ rằng lỗi là do thực tế là nếu mẫu không phải là variadic, thì cpomiler mong đợi biểu mẫu chuẩn, đó là lớp Event<templateArg1, templateArg2>, rõ ràng không phải là những gì bạn đang cung cấp.

Giới thiệu về chuyên môn mẫu: Tôi không đồng ý, nếu tôi không sai những gì bạn đang làm có để chuyển tiếp khai báo lớp Event, sau đó khai báo hiệu quả chỉ 2 dòng sau.

+0

Điều đó có nghĩa là nếu chúng ta muốn một mẫu chấp nhận một kiểu hàm làm đối số mẫu, chúng ta chỉ có thể sử dụng các đối số variadic? Điều tôi muốn là giới hạn loại hàm chỉ với một đối số.Tôi đã sửa đổi mã để bây giờ chúng là tất cả các định nghĩa. –

+0

Xin lỗi phải thay đổi chúng trở lại các tờ khai chuyển tiếp ngay bây giờ để tránh nhầm lẫn mọi người với mục đích của nó, vì tôi đã thêm một định nghĩa đơn giản cho phiên bản chuyên dụng. Phiên bản chung không thể được khởi tạo bởi vì nó không triển khai thực hiện. Đó là theo mục đích. –

+0

"Điều đó có nghĩa là nếu chúng ta muốn một mẫu chấp nhận một kiểu hàm làm đối số mẫu, chúng ta chỉ có thể sử dụng các đối số variadic?" có và không. Nếu không có đối số variadic, bạn phải tạo các mẫu khác nhau cho số đối số khác nhau. Nó khá phổ biến. Xem ví dụ https://github.com/pisto/hopmodv4/blob/master/src/hopmod/lua/push_function.hpp –

5

Nếu bạn muốn chắc phiên bản của riêng bạn std::function cho vui, nó sẽ giống như thế này:

template<class Signature> 
class Event; 

template<class R, class... Args> 
class Event<R(Args...)>{ 
    // ... 
}; 

Tại sao phiên bản đầu tiên của bạn hoạt động đã được giải thích bởi @ronag, một gói thông số (... trong mẫu tham số) có nghĩa là không hoặc hơn. Mã tôi đã cung cấp ở trên vẫn là chữ ký chính xác nếu bạn muốn một lớp std::/boost::function giống như (int(int, double, char) là một loại chức năng, đó là lý do tại sao nó có thể phù hợp với một tuyên bố kiểu đơn như class Signature).

+0

"... là một loại chức năng, đó là lý do tại sao nó có thể phù hợp với một khai báo kiểu đơn như lớp Chữ ký)." - Vì vậy, có vẻ như câu trả lời là, một loại hàm, như int (int, double), được xử lý bởi trình biên dịch như là một khai báo kiểu đơn? –

+0

@H Xu: Đúng, đó là một loại duy nhất. – Xeo

+0

Cảm ơn Xeo, câu trả lời của bạn truyền cảm hứng cho tôi với nguyên nhân gốc rễ. Câu trả lời của @ ronag có vẻ hơi khó khăn đối với những người xem khác vì vậy tôi đã đánh dấu màu xanh lá cây cho anh ấy. –

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