2012-07-21 11 views
5

मेरी वर्तमान परियोजना के लिए, मैं लूआ रैपर को बहुत सी सी/सी ++ लिख रहा हूं। इनमें से एक बड़ी संख्या में सरल setters और getters हैं, इसलिए मैं कुछ टेम्पलेट्स कि, यह आसान इन उत्पन्न करने के लिए बनाने के इतने तरह लिखने में सफल:सामान्य लूआ फ़ंक्शन रैपर बनाने के लिए वैरैडिक टेम्पलेट्स का उपयोग कैसे करें?

//  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> }, 
    ... 
}; 

मैं मनमाना कार्यों के लिए सरल समारोह रैपर के लिए कुछ इसी तरह करना चाहते हैं भी। उदाहरण के लिए, यह ऐसा करने के लिए सक्षम होने के लिए अच्छा होगा:

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> }, 
    ... 
}; 

विचार यह है कि टेम्पलेट को प्रभावी ढंग से बाहर कर देते हैं इस होना करने के लिए जब संकलित: बस का उपयोग कर

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; 
} 

मैं कोशिश की है ... विस्तारक, मेरे लिए समस्या उचित तर्कों को मैप करने के लिए पूर्णांक सूचकांक मान है। मैं उन्हें सही काम करने के तरीके के बारे में नहीं सोच सकता। क्या ऐसी चीज भी संभव है?

(वहाँ जादू पहले से ही यहाँ पर जा रहा का एक छोटा सा है, मैं lua_push और lua_check जैसी चीजों के लिए कुछ टेम्प्लेट की गई रैपर लिखा उन मौजूदा रैपर के सभी here पाया जा सकता है।)

+0

क्या आपने [luabind] (http://www.rasterbar.com/products/luabind.html) पर एक नज़र डाली है? –

+0

क्या आप सुझाव दे रहे हैं कि मैं लुबाइंड का उपयोग करता हूं? या उन्होंने एक ऐसी समस्या हल की जिसे मैं संदर्भ के लिए उपयोग कर सकता हूं? (मुझे कई कारणों से मेरी परियोजना के लिए लुइबिंड का उपयोग करने में दिलचस्पी नहीं है।) – Alex

+1

मुझे यकीन नहीं था कि आप इसके बारे में जानते हैं या नहीं। वैसे भी, तर्क और अनुक्रमणिका समस्या के लिए, [यहां मूल विचार है] (http://stackoverflow.com/a/8028333/168225)। –

उत्तर

5

चाल आंशिक रूप से एक वर्ग विशेषज्ञता द्वारा टेम्पलेट तर्क कटौती का फायदा उठाने की है टेम्पलेट जिसमें रैपर मज़ा शामिल है 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); 
} 

इस कोड विकल्पों का उपयोग कर जी के तहत ++ 4.6.1 संकलित -c --std = C++ 0x। यह देखने के लिए कि क्या आप वास्तव में जो चाहते हैं वह करते हैं, कृपया इसे जांचें ...

+0

मैंने अभी इसका परीक्षण किया है और ऐसा लगता है कि मैं वैसे ही काम करता हूं, आपको बहुत धन्यवाद: डी इस जवाब को देखते हुए मुझे कम बुरा लगता है कि मैं इसे स्वयं नहीं समझ पाया। – Alex

2

this answer से सूचकांक पीढ़ी कोड पुनर्प्रयोग और अनदेखी Func को समारोह कॉल (यह कैसे का उपयोग किए जाने का इरादा है पता नहीं है), तो यह दिखाई दे सकता है कि कैसे:

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

यह काम नहीं करता है, कम से कम जैसा कि आप यहां दिखाते हैं ... फ़ंक्शन पॉइंटर 'यू (टी :: * Func)() 'कोई तर्क नहीं लेता है। – Alex

+0

मैंने अभी जो आपने ऊपर दिखाया है उसका उपयोग किया - आप किस फ़ंक्शन प्रकार का उपयोग करना चाहते हैं? –

+0

कोई भी सदस्य फ़ंक्शन जो मनमाने ढंग से तर्क ले सकता है - मेरा उदाहरण काम नहीं करता है, जो समस्या मैं हल करने की कोशिश कर रहा हूं। – Alex

संबंधित मुद्दे