2012-06-25 49 views
6

Gần đây tôi đã làm việc với libffi và vì nó sử dụng API C, bất kỳ trừu tượng nào được thực hiện bằng cách sử dụng con trỏ void (tốt ol 'C). Tôi đang tạo một lớp (với các mẫu variadic) sử dụng API này. Khai báo lớp như sau: (nơi Ret = giá trị trả về và Args đối số = function)Các mẫu biến thể: lặp qua đối số kiểu/mẫu

template <typename Ret, typename... Args> 
class Function 

Trong lớp học này tôi có hai chức năng khác nhau tuyên bố cũng như (giản thể):

Ret Call(Args... args); // Calls the wrapped function 
void CallbackBind(Ret * ret, void * args[]); // The libffi callback function (it's actually static...) 

Tôi muốn để có thể sử dụng Call từ CallbackBind; và đó là vấn đề của tôi. Tôi không có ý tưởng làm thế nào tôi có nghĩa vụ phải chuyển đổi các mảng void* vào danh sách đối số templated. Đây là những gì tôi muốn nhiều hơn hoặc ít hơn:

CallbackBind(Ret * ret, void * args[]) 
{ 
// I want to somehow expand the array of void pointers and convert each 
// one of them to the corresponding template type/argument. The length 
// of the 'void*' vector equals sizeof...(Args) (variadic template argument count) 

// Cast each of one of the pointers to their original type 
*ret = Call(*((typeof(Args[0])*) args[0]), *((typeof(Args[1])*) args[1]), ... /* and so on */); 
} 

Nếu điều này là không thể đạt được, có giải pháp khác hoặc các giải pháp khác nhau có sẵn không?

+1

Có lý do nào khiến bạn không thể gọi trực tiếp vào API của thư viện từ cuộc gọi lại không? Bạn đã có một 'void *', và nó đã mong đợi điều đó. –

+0

Mmm lý do tại sao bạn muốn gọi hàm mẫu variadic với số lượng đối số cố định? Dựa trên thực tế là "chiều dài của args bằng sizeof ... (Args)", sau đó bạn biết số lượng các đối số cần thiết, tại sao sử dụng các mẫu variadic ?. – mfontanini

+0

@MarkB Vì 'CallbackBind' được gọi là _from_ API của thư viện Tôi đang cố gắng gọi hàm của riêng mình mà không sử dụng con trỏ void. @mfontanini Tôi muốn một lớp bắt chước 'std :: function', và do đó tôi yêu cầu các mẫu variadic (chẳng hạn như' operator() (Args ...) ') –

Trả lời

5

Bạn không muốn lặp qua các loại, bạn muốn tạo một gói tham số và mở rộng nó trong một mẫu variadic. Bạn có một mảng, vì vậy gói bạn muốn là một gói các số nguyên 0,1,2 ... để phục vụ như là chỉ mục mảng.

#include <redi/index_tuple.h> 

template<typename Ret, typename... Args> 
struct Function 
{ 
    Ret (*wrapped_function)(Args...); 

    template<unsigned... I> 
    Ret dispatch(void* args[], redi::index_tuple<I...>) 
    { 
    return wrapped_function(*static_cast<Args*>(args[I])...); 
    } 

    void CallbackBind(Ret * ret, void * args[]) 
    { 
    *ret = dispatch(args, to_index_tuple<Args...>()); 
    } 
}; 

Something như vậy, sử dụng index_tuple.h

Bí quyết là CallbackBind tạo ra một index_tuple các số nguyên đại diện cho các vị trí arg, và công văn đến một chức năng mà deduces các số nguyên và mở rộng các gói vào một danh sách các diễn viên biểu thức để sử dụng làm đối số cho hàm được bao bọc.

+0

Thật là một giải pháp thanh lịch! Làm việc hoàn hảo cho tôi. –

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