2012-06-25 38 views
6

Son zamanlarda libffi ile çalışıyorum ve bir C API kullandığından, herhangi bir soyutlama void işaretçiler (iyi ol 'C) kullanılarak yapılır. Bu API'yi kullanan bir sınıf (variadic şablonlarla) oluşturuyorum. sınıf bildirimi aşağıdadır: (burada Ret = dönüş değeri ve Args = fonksiyon argümanlar) Bu sınıf içindeVariadic şablonları: type/template argümanı üzerinde yineleme

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

I (basitleştirilmiş), iki farklı işlevleri de ilan var: istediğim

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

Call'u CallbackBind'dan kullanabilmek; ve bu benim problemim. void* dizisini şablonlanmış argüman listesine nasıl dönüştüreceğimi bilmiyorum. Bu ulaşılabilir değilse herhangi geçici çözümler veya farklı çözüm mevcuttur,

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

: Bu benim az ya da çok istediğin bu mu?

+1

Kitaplığın doğrudan API'sini arayabilmeniz için bir neden var mı? Zaten bir * void * var ve zaten bunu bekliyor. –

+0

Mmm neden değişken bir argüman ile değişken bir şablon işlevini çağırmak istersiniz? "Args uzunluğunun büyüklüğü eşittir ... (Args)" gerçeğine dayanarak, gerekli argüman sayısını biliyorsunuz, neden variadic şablonlarını kullanıyorsunuz? – mfontanini

+0

@MarkB 'CallbackBind' den beri _from_ kütüphanenin API'sı void işaretçileri kullanmayan kendi işlevimi çağırmaya çalışıyorum. @mfontanini std :: function' kelimesini taklit eden bir sınıf istiyorum ve bu yüzden de variadic şablonlara ihtiyacım var (örneğin, operator() (Args ...) ') –

cevap

5

Türler üzerinde yineleme yapmak istemezsiniz, bir parametre paketi oluşturmak ve bunu değişken bir şablonda genişletmek istiyorsunuz. Bir diziniz var, yani istediğiniz paket bir dizi indeks olarak işlev görmek için ... ... bir tamsayıdır. index_tuple.h

hile kullanarak böyle

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

şey, CallbackBind tamsayılar deduces ve döküm bir liste halinde paketi genişler başka bir işleve oluşturur arg pozisyonlarını temsil eden tamsayılar index_tuple ve harekât olmasıdır Sarılmış işleve argüman olarak kullanılacak ifadeler.

+0

Ne kadar zarif bir çözüm! Benim için kusursuz bir şekilde çalıştı. –

İlgili konular