2011-12-31 34 views
0

我迷失了模板。boost :: tuple和generic結構體的不同模板專業化

我有這樣的代碼在頭:

void push(lua_State *, bool); 
void push(lua_State *, int); 
void push(lua_State *, long); 
void push(lua_State *, unsigned long); 
void push(lua_State *, lua_Number); 
void push(lua_State *, lua_CFunction); 
void push(lua_State *, const char *); 
void push(lua_State *, const char *, std::size_t); 
void push(lua_State *, const std::string &); 

template<typename T> 
void push(lua_State * L, const std::vector<T> & value) 
{ 
    lua_newtable(L); 
    std::size_t size = value.size(); 
    for(unsigned int i = 0; i < size; i++) 
    { 
     lua_pushinteger(L, i + 1); 
     push(L, value[i]); 
     lua_settable(L, -3); 
    } 
} 

inline void push(lua_State *, boost::tuples::null_type){} 
inline void push(lua_State *, boost::tuple<>){} 

template<typename HT, typename TT> 
void push(lua_State * L, const boost::tuples::cons<HT, TT> & value){ 
    push(L, value.get_head()); 
    push(L, value.get_tail()); 
} 

//Declared but not defined. *Intentional* compile-time error if trying to push a Luaproxy (undefined reference). Use Lua stack reference instead 
template<typename T> 
void push(lua_State* l, Luaproxy<T>& value); 

template<typename T>  //most generic version 
void push(lua_State* l, T& value){ 
    Luaproxy<T>::new_c(l, value, false); 
} 

我希望看到boost::tuples::conspush()調用時爲第二個參數傳遞的boost::make_tuple(...)結果。但是我在鏈接時遇到錯誤,表明這些調用已解析爲push的最普通版本,即push(lua_State* l, T& value)

最終的結果是,我一定能夠做到

mystruct example; 
push(l, boost::make_tuple(3, 4, example)) 

而這又必須

void push(lua_State * L, const boost::tuples::cons<HT, TT> & value) //tuple contains int, int, mystruct 
void push(lua_State *, int) 
void push(lua_State * L, const boost::tuples::cons<HT, TT> & value) //my tuple contains int mystruct 
void push(lua_State *, int) 
void push(lua_State * L, const boost::tuples::cons<HT, TT> & value) //my tuple contains mystruct 
void push(lua_State* l, T& value) 

調用如果我刪除我的push()功能最普遍的形式,其餘我的應用程序的代碼,它調用push()與作爲參數的一個typle正確解析到push(lua_State * L, const boost::tuples::cons<HT, TT> & value)版本的函數。所以,出於某種原因,最通用的版本具有更高的優先級,這就是我不想要的。

編輯: 我試圖按照Anycorn的建議,但我不是很擅長這一點。我要離開boost::tuples::cons版本是,我想禁用如果將參數從boost::tuples::cons得出的通用版本:

template<typename T, typename HT, typename TT> 
void push(lua_State* l, T& value, typename boost::disable_if<boost::is_base_of< boost::tuples::cons<HT, TT>, T>, T>::type* =0){ 
    Luaproxy<T>::new_c(l, value, false); 
} 

而且它仍在考慮利弊鍵入push(l, boost::make_tuple(mystruct))

[切] /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:48:6:note:template void lua :: push(lua_State *,lua :: Luaproxy &) /home/pisto/sorgenti /hopmodv4/src/hopmod/lua/push_function.hpp:51:6:note:template void lua :: push(lua_State *,const T &, typename boost :: disable_if,T>,T> :: type *) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:56:6:note:template void lua :: push(lua_State *,常量的boost ::元組::利弊&)

+1

好像你正在嘗試做部分專業化的功能 - 你不能 – Anycorn 2011-12-31 00:42:26

回答

1

template<> template<typename HT, typename TT> 
void push< boost::tuples::cons<HT, TT> >(lua_State * L, const boost::tuples::cons<HT, TT> & value){ 
    push(L, value.get_head()); 
    push(L, value.get_tail()); 
} 

應該

template<typename HT, typename TT> 
void (lua_State * L, const boost::tuple<HT, TT> & value){ 
    push(L, value.get_head()); 
    push(L, value.get_tail()); 
} 

通知,make_tuple返回元組,而不是缺點。

如果我理解你的問題正確

更新:

元組從利弊繼承。如果參數不是cons的派生項,並且啓用它,則必須做的是通用模板失敗。

http://www.boost.org/doc/libs/1_48_0/libs/utility/enable_if.html

http://www.boost.org/doc/libs/1_36_0/libs/type_traits/doc/html/boost_typetraits/reference/is_base_of.html

或者你可以專門元組模板功能和流延元組的基礎上,cons

更新:

看到你嘗試做你需要一種方法是什麼測試一個元組: 讓我們試試這個:

template<class T> 
is_tuple : boost::mpl::false_ {}; 

template<class T0, class T1, ...> 
struct is_tuple<tuple<T0, T1, ..> > : boost::mpl::true_ {}; 

然後寫功能禁用/啓用取決於元組和功能來處理cons<H,T>。元組函數必須調用cons函數。

+0

不,你被我的例子誤導了:元組可以是任意數量的參數。我已經修改了問題中的示例,使其更加清晰。據我所知,唯一的做一個任意數量的參數的元組push()是使用這種「遞歸元編程」與boost :: tuples :: cons_get_head()(它返回第一個參數單獨)和boost :: tuples :: cons_get_tail()(它會返回一個帶有從原始缺點中刪除的第一個參數的缺點) – 2011-12-31 08:53:50

+0

我修改了這個問題來解釋我爲什麼使用cons。它沒有push()的最普通版本。 – 2011-12-31 09:03:21

+0

好的,得到了​​,見第二個更新 – Anycorn 2011-12-31 09:10:13