различная специализация шаблонов для boost :: tuple и родовых структур - PullRequest
0 голосов
/ 31 декабря 2011

Я заблудился с шаблонами.

У меня есть этот код в заголовке:

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::cons версию push(), вызываемую как второйаргумент передается в результате 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 as корректно разрешен в push(lua_State * L, const boost::tuples::cons<HT, TT> & value) версии функции.Итак, по какой-то причине самая общая версия имеет более высокий приоритет, а это то, чего я не хочу.

edit: я пытаюсь следовать предложению 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);
}

, и он все еще рассматривает тип cons для push(l, boost::make_tuple(mystruct))

[вырезать] /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:48:6: примечание: шаблон void lua :: push (lua_State *, lua ::Luaproxy &) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:51:6: note: шаблон void lua :: push (lua_State *, const T &, повышение имени типа :: disable_if, T>, T> :: type *) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:56:6: note: шаблон void lua :: push (lua_State *, повышение констант :: кортежи :: cons &)

1 Ответ

1 голос
/ 31 декабря 2011

это

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...