I’m lost with templates.
I have this code in a header:
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);
}
I expect to see the boost::tuples::cons version of push() called when as second argument is passed a result of boost::make_tuple(...). But I get errors at linking that show that such calls are resolved to the most generic version of push, that is push(lua_State* l, T& value).
The final result is that I must be able to do
mystruct example;
push(l, boost::make_tuple(3, 4, example))
and this must call in turn
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)
If I delete the most general form of my push() functions, the rest of the code of my application, where it calls push() with a typle as argument is correctly resolved to the push(lua_State * L, const boost::tuples::cons<HT, TT> & value) version of the function. So, for some reason the most generic version has an higher priority, and that’s what I don’t want.
edit:
I’m trying to follow Anycorn’s suggestion, but I’m not very good at this. I’m leaving the boost::tuples::cons version as is, and i want to disable the generic version if the argument is derived from 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);
}
and it’s still considering the cons type for push(l, boost::make_tuple(mystruct))
[cut]
/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*, const boost::tuples::cons&)
this
should be
notice that make_tuple returns tuple, not cons.
if i understood your question correctly
update:
tuple inherits from cons. what you must do is fail the generic template if argument isn’t derivative of cons and enable it otherwise.
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
alternatively you can specialize tuple template function and cast tuple to its base,
consupdate:
seeing what you try to do you need a way to test a tuple:
lets try this:
then write function to disable/enable depending on tuple AND a function to handle
cons<H,T>. Tuple function must call cons function.