2015-01-19 14 views
6

Có cách nào để tôi có thể trích xuất các loại từ chữ ký hàm trong biểu mẫu foo(bar) và truy cập chỉ foo hoặc bar. Vì vậy, nếu tôi có mẫu:Bạn có thể trích xuất các loại từ chữ ký mẫu chức năng tham số

template<typename signiture> 
class type{ 
}; 

nơi signiture là foo(bar) và sau đó có một chức năng trong lớp mà đọc

foo function(bar b){ 
    //do stuff 
} 

Tôi interfacing với std::function và đã tìm thấy nó thuận tiện hơn để sử dụng foo(bar) cú pháp thay vì sử dụng nhiều thông số mẫu như vậy:

template<typename return_t,param_tps... args> 
class type{ 
    return_t function(param_ps args...){ 
     return something; 
    } 
}; 

Hãy cho tôi biết nếu tôi có thể làm rõ? Cảm ơn trước.

EDIT: để làm rõ tôi quan tâm đến một hàm có số tham số N được xác định bởi bất kỳ trường hợp lớp cụ thể nào xác định.

EDIT 2: Mã rằng câu hỏi này được dựa tắt của là như sau:

using std::function; 
template <typename signiture> 
class Observer; 

template <typename return_t, typename ...args_t> 
class Observer<return_t(args_t...)> { 
protected: 
    using signature = return_t(args_t...); 
    typedef function<signature> func_t; 
    ~Observer(){} 
    func_t what_to_do; 
public: 
    Observer(Subject<signature>& subject,func_t what):what_to_do(what){ 
     subject.Attach(what_to_do); 
    } 
    return_t operator()(args_t... args){ 
     what_to_do(args...); 
    } 
}; 

using std::function; 
using std::vector; 
template <typename signature> 
class Subject; 

template <typename return_t,typename...param_tps> 
class Subject<return_t(param_tps...)> { 
    using signature=return_t(param_tps...); 
public: 
    void Attach(std::function<signature> o){ 
     obs.push_back(o); 
    } 
    void operator()(param_tps... params){ 
     for (typename vector<std::function<signature>>::const_iterator i=obs.begin(); i!=obs.end(); ++i) { 
      (*i)(params...); 
     } 
    } 
protected: 
    ~Subject(){} 
    vector<std::function<signature>> obs; 

}; 

Đó là một thực hiện các mô hình Observer đó là không ảo sử dụng std::function để keo việc cùng nhau giữa hai . Tôi muốn sử dụng cú pháp foo(bar) vì mọi thứ đều có lợi cho việc sử dụng dễ dàng các lớp học. Sự cố đã chuyển đổi chữ ký loại hàm thành kiểu trả về và các kiểu tham số để chỉ định operator() thích hợp trong lớp chủ đề để nó có thể thông báo cho các quan sát viên bằng đúng dữ liệu.

Những thay đổi đã được thực hiện dựa trên những nguồn ví dụ đưa ra dưới đây như sau:

template<typename t>struct type; 
template<typename R,typename... args_t> 
struct type<R(args_t...)>{ 
//use R and args_t as needed 
} 

Nhờ tất cả những ai giúp đỡ.

+0

phần chuyên môn hóa? – Columbo

+0

@Columbo ý bạn là gì? thí dụ? –

+0

Xem câu trả lời ở dưới đó VVVV – Columbo

Trả lời

6

Dưới đây là một giải pháp rất cơ bản mà làm việc cho các chức năng chấp nhận một tham số (có vẻ như bạn đang đặt ràng buộc này trong câu hỏi, nhưng một giải pháp tổng quát là khá dễ dàng để cung cấp, như thể hiện trong những điều sau đây):

template<typename S> 
struct type; // You can leave this undefined, because the template is 
      // supposed to be instantiated with a function type, and 
      // that is matched by the specialization below. 

template<typename R, typename Arg> 
struct type<R(Arg)> 
{ 
    // Just use R and Args as you wish here.. 
}; 

Dưới đây là một ví dụ tốt (live demo on Coliru):

#include <type_traits> 

template<typename S> 
struct signature; 

template<typename R, typename Arg> 
struct signature<R(Arg)> 
{ 
    using return_type = R; 
    using argument_type = Arg; 
}; 

int main() 
{ 
    using ret = signature<void(int)>::return_type; 
    using arg = signature<void(int)>::argument_type; 

    static_assert(std::is_same<ret, void>{}, "!"); 
    static_assert(std::is_same<arg, int>{}, "!"); 
} 

trong trường hợp bạn đang quan tâm đến một giải pháp tổng quát hơn đối với trường hợp variadic, đây có lẽ là những gì bạn đang tìm kiếm:

#include <tuple> 

struct type; // You can leave this undefined, because the template is 
      // supposed to be instantiated with a function type, and 
      // that is matched by the specialization below. 

template<typename R, typename... Args> 
struct type<R(Args...)> 
{ 
    // Just use R and Args... as you with here.. 
}; 

Và đây là một cách sử dụng ví dụ có thể (live demo on Coliru):

#include <tuple> 
#include <type_traits> 

template<typename S> 
struct signature; 

template<typename R, typename... Args> 
struct signature<R(Args...)> 
{ 
    using return_type = R; 
    using argument_type = std::tuple<Args...>; 
}; 

int main() 
{ 
    using ret = signature<void(int, double)>::return_type; 
    using arg1 = std::tuple_element_t<0, signature<void(int, double)>::argument_type>; 
    using arg2 = std::tuple_element_t<1, signature<void(int, double)>::argument_type>; 

    static_assert(std::is_same<ret, void>{}, "!"); 
    static_assert(std::is_same<arg1, int>{}, "!"); 
    static_assert(std::is_same<arg2, double>{}, "!"); 
} 
+0

Có cách nào để biến nó thành variadic không? sao cho nó sẽ hoạt động với bất kỳ số tham số nào mà không phải quá tải một bó? –

+0

@AlexZywicki: Tôi đã thêm một khái quát, mặc dù đây có phải là loại khái quát hóa mà bạn đang tìm kiếm có lẽ phụ thuộc vào trường hợp sử dụng cụ thể của bạn cho đặc điểm này hay không. –

+0

Tôi tin rằng tôi chỉ cần tách kiểu trả về và các đối số của nhau. Tôi không cần phải truy cập mỗi loại đối số chỉ là các đối số như một danh sách các loại nếu điều đó có ý nghĩa. Vì vậy, tôi sẽ nhận được 'foo' và' bar ... 'từ' foo (bar ...) ' –

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