2012-01-30 28 views
23

Đây là một tiếp lên các vấn đề này: Generic functor for functions with any argument listLàm cách nào để nhận được các kiểu đối số của một con trỏ hàm trong lớp mẫu variadic?

Tôi có lớp này functor (mã đầy đủ thấy liên kết ở trên):

template<typename... ARGS> 
class Foo 
{ 
    std::function<void(ARGS...)> m_f; 
    public: 
    Foo(std::function<void(ARGS...)> f) : m_f(f) {} 
    void operator()(ARGS... args) const { m_f(args...); } 
}; 

Trong điều hành() Tôi có thể truy cập vào args ... một cách dễ dàng với chức năng "lột" đệ quy như được mô tả ở đây http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates

Vấn đề của tôi là: Tôi muốn truy cập các loại đối số của f, tức là ARGS ..., trong hàm tạo. Rõ ràng là tôi không thể truy cập các giá trị bởi vì không có giá trị nào cho đến nay, nhưng danh sách kiểu đối số được bằng cách nào đó được chôn trong f, phải không?

Trả lời

48

Bạn có thể viết function_traits lớp như hình dưới đây, để khám phá các loại đối số, kiểu trả về, và số lượng các đối số:

template<typename T> 
struct function_traits; 

template<typename R, typename ...Args> 
struct function_traits<std::function<R(Args...)>> 
{ 
    static const size_t nargs = sizeof...(Args); 

    typedef R result_type; 

    template <size_t i> 
    struct arg 
    { 
     typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; 
    }; 
}; 

mã kiểm tra:

struct R{}; 
struct A{}; 
struct B{}; 

int main() 
{ 
    typedef std::function<R(A,B)> fun; 

    std::cout << std::is_same<R, function_traits<fun>::result_type>::value << std::endl; 
    std::cout << std::is_same<A, function_traits<fun>::arg<0>::type>::value << std::endl; 
    std::cout << std::is_same<B, function_traits<fun>::arg<1>::type>::value << std::endl; 
} 

Demo: http://ideone.com/YeN29

+0

Cảm ơn bạn @Nawaz, hoạt động cho đến nay. Tuy nhiên, tôi muốn trích xuất "ma thuật" ra khỏi giải pháp này và đặt nó vào mã của tôi. Tôi giả sử typename std :: tuple_element > :: type là nơi nó xảy ra ... Làm thế nào để làm điều đó mà không cần phải khai báo một cấu trúc khác – steffen

+0

@steffen: Bạn có bất kỳ vấn đề trong việc xác định cấu trúc khác có thể được sử dụng trong các tình huống khác? Ngoài ra, đặt tất cả các mã trong một lớp học không phải là một ý tưởng tốt. Cố gắng chia mã thành các đơn vị làm việc nhỏ. – Nawaz

+0

Tôi hiểu rõ vấn đề của bạn. Một câu hỏi cuối cùng là đoạn mã này từ thư viện tăng? function_traits có vẻ quen thuộc;) – steffen