2012-06-25 142 views
6

我一直與libffi近來,由於它採用的是C API,任何抽象是通過使用空指針(好醇」 C)來完成。我正在創建一個使用此API的類(使用variadic模板)。類的聲明如下:(其中Ret =返回值和Args =函數參數)可變參數模板:迭代式/模板參數

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

在這個班,我有兩個不同的功能聲明以及(簡化):

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

我想能夠從CallbackBind使用Call;這是我的問題。我不知道我應該如何將void*數組轉換爲模板參數列表。這是我想要的更多或更少:

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 */); 
} 

如果這不能實現,是否有任何解決方法或不同的解決方案可用?

+1

是否有一個原因,你不能只是直接調用從回調庫的API?你已經有了一個'void *',並且它已經期待這一點。 –

+0

嗯爲什麼你想要用固定數量的參數調用可變參數模板函數?基於「args的長度等於sizeof ...(Args)」的事實,那麼你知道需要的參數的數量,爲什麼要使用可變參數模板? – mfontanini

+0

@MarkB由於'CallbackBind'被稱爲_from_庫的API我試圖調用我自己的函數,它不使用void指針。 @mfontanini我想要一類模仿'的std :: function',因此我需要可變參數模板(如'運算符()(參數...)') –

回答

5

你不想遍歷類型,你想創建一個參數包和擴大它在一個可變參數模板。你有一個數組,所以你想要的包是一組整數0,1,2 ...作爲數組索引。

#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...>()); 
    } 
}; 

類似的東西,使用index_tuple.h

訣竅是,CallbackBind創建表示ARG位置整數的index_tuple,並分派給其推導出整數和包擴展到投列表另一個功能表達式用作包裝函數的參數。

+0

多麼優雅的解決方案!爲我完美無瑕地工作。 –