2012-07-21 22 views
5

Şu anki projemde, Lua sarma makinelerine çok fazla C/C++ yazdım. Bunların büyük bir kısmı basit belirleyiciler ve odaklar, bu yüzden, bu kolay bu oluşturulmasına yardımcı öylesine gibi bazı şablonları yazmayı başardı: Ben keyfi fonksiyonlar için basit fonksiyon sarýcýlarý benzer bir şey yapmak istiyorumGenel bir Lua işlev sarıcı yapmak için variadic şablonları nasıl kullanılır?

//  Class  Return  Field 
template <typename T, typename U, U T::*Member> 
int luaU_get(lua_State* L) 
{ 
    T* obj = luaW_check<T>(L, 1); 
    luaU_push<U>(L, obj->*Member); 
    return 1; 
} 

static luaL_reg Foo_Table[] = 
{ 
    ... 
    // Now I can just use this generic template to avoid 
    // writing simple getter functions 
    { "getbar", luaU_get<Foo, Bar, &Foo::bar> }, 
    ... 
}; 

çok. Örneğin, bu yapabilmek için iyi olurdu:

template <typename T, typename U, U (T::*Func)(), typename... Args> 
int luaU_func(lua_State* L) 
{ 
    // ...? 
} 

static luaL_reg Foo_Table[] = 
{ 
    ... 
    { "baz", luaU_func<Foo, int, &Foo::baz, int, float> }, 
    ... 
}; 

fikri derlenmiş zaman şablon etkili bu haline gelmek olduğunu:

int luaU_func(lua_State* L) 
{ 
    luaU_push<int>(L, luaW_check<Foo>(L, 1)->baz(luaU_check<int>(L, 2), luaU_check<float>(L, 3))); 
    return 1; 
} 

denedim sadece kullanılarak ... expander, benim için problem uygun argümanlara eşlenecek tamsayı indeks değerleridir. Onları doğru şekilde çalıştırmanın bir yolunu düşünemiyorum. Böyle bir şey mümkün mü?

(sihirli zaten burada devam biraz var; ben lua_push ve lua_check gibi şeyler için bazı templated sarmalayıcılarını yazdığı bu mevcut sarmalayıcılarının tamamı here bulunabilir.)

+0

[luabind] 'e bakabilirsiniz mu (http://www.rasterbar.com/products/luabind.html)? –

+0

Luabind'i kullanmanızı mı öneriyorsunuz? Ya da referans için kullanabileceğim benzer bir sorunu çözdüler mi? (Projem için bir dizi nedenden dolayı luabind kullanmak istemiyorum.) – Alex

+1

Sadece bunu biliyor olsaydınız emin değildim. Her neyse, argüman & index problemi için, [burada temel fikir] (http://stackoverflow.com/a/8028333/168225). –

cevap

5

hile kısmen bir sınıf uzmanlaşmış tarafından şablon argümanı kesinti istismar etmektir: ve Func işlev çağrısını görmezden, buna benzerdi nasıl olduğunu (bu kullanılmak üzere tasarlanmıştır tam olarak nasıl bilmiyorum) sarmalayıcı eğlenceli içeren şablon ction:

// Lua API dummies ... 

struct lua_State {}; 

template<class T> void luaU_push(lua_State*,T); 
template<class T> T* luaW_check(lua_State*,int); 
template<class T> T luaU_check(lua_State*,int); 


// metaprogramming for creating indices ... 

template<int...Ints> 
struct int_pack {}; 

template<int Begin, int Count, int...Tail> 
struct make_int_range_type { 
    typedef typename make_int_range_type<Begin,Count-1,Begin+Count-1,Tail...>::type type; 
}; 

template<int Begin, int...Tail> 
struct make_int_range_type<Begin,0,Tail...> { 
    typedef int_pack<Tail...> type; 
}; 

template<int Begin, int Count> 
inline typename make_int_range_type<Begin,Count>::type 
make_int_range() 
{ return typename make_int_range_type<Begin,Count>::type(); } 


// the actual wrapper ... 

template<class MemFunPtrType, MemFunPtrType PMF> 
struct lua_mem_func_wrapper; 

template<class Clazz, class ReturnType, class...Args, ReturnType(Clazz::*PMF)(Args...)> 
struct lua_mem_func_wrapper<ReturnType(Clazz::*)(Args...),PMF> { 
    static int doit(lua_State* L) { 
     return doit_impl(L,make_int_range<2,sizeof...(Args)>()); 
    } 
private: 
    template<int...Indices> 
    static int doit_impl(lua_State* L, int_pack<Indices...>) { 
     luaU_push<ReturnType>(L, 
      (luaW_check<Clazz>(L, 1)->*PMF)(
       luaU_check<Args>(L, Indices)... 
      ) 
     ); 
     return 1; 
    } 
}; 

#define GET_MEM_FUN_WRAPPER(...) &lua_mem_func_wrapper<decltype(__VA_ARGS__),__VA_ARGS__>::doit 


// testing ... 

struct foo { 
    int baz(int, float); 
}; 

void test() { 
    auto* ptr = GET_MEM_FUN_WRAPPER(&foo::baz); 
} 

Bu kod seçenekleri kullanarak 4.6.1 ++ G altında derler -c --std = C++ 0x. Gerçekten istediğini yapıp yapmadığını görmek için, lütfen test edin ...

+0

Sadece bunu test ettim ve tam olarak istediğim gibi çalışıyor görünüyorum, çok teşekkür ederim: D Bu cevabı görmem, kendimi daha iyi anlayamıyorum. – Alex

2

this answer gelen endeksleri nesil kodunu tekrar kullanımı

template <typename T, typename U, U (T::*Func)(), 
      typename... Args, size_t... Idx> 
int luaU_func_impl(lua_State* L, Collection<Idx...>) 
{ 
    luaU_push<int>(L, luaW_check<U>(L, 1), luaU_check<Args>(L, Idx+2)...); 
    return 1; 
} 

template <typename T, typename U, U (T::*Func)(), typename... Args> 
int luaU_func(lua_State* L) 
{ 
    typename GenerateCollection<Args...>::type Indices; 
    return luaU_func_impl<T, U, Func, Args...>(L, Indices); 
} 
+0

Bu, en azından burada gösterdiğiniz gibi çalışmaz ... İşlev işareti 'U (T :: * Func)()' hiçbir argüman almaz. – Alex

+0

Sadece yukarıda gösterdiğiniz şeyi kullandım - hangi işlev türlerini kullanmak istiyorsunuz? –

+0

Rasgele argümanlar alabilecek herhangi bir üye işlevi - benim örneğim çalışmıyor, çözmeye çalıştığım sorun bu. – Alex