【问题标题】:different template specialization for boost::tuple and generic structsboost::tuple 和泛型结构的不同模板特化
【发布时间】:2012-01-30 21:48:11
【问题描述】:

我迷失了模板。

我在标题中有这段代码:

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

我希望看到push()boost::tuples::cons 版本在作为第二个参数传递boost::make_tuple(...) 的结果时被调用。但我在链接时遇到错误,表明此类调用已解析为push 的最通用版本,即push(lua_State* l, T&amp; 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(),将正确地解析为函数的push(lua_State * L, const boost::tuples::cons&lt;HT, TT&gt; &amp; 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)) 的 cons 类型

[剪切] /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:48:6: 注意:模板无效 lua::push(lua_State*, lua::Luaproxy&) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:51:6: 注意:模板 void lua::push(lua_State*, const T&, typename boost::disable_if, T>, T>: :类型*) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:56:6: 注意:模板 void lua::push(lua_State*, const boost::tuples::cons&)

【问题讨论】:

  • 似乎您正在尝试对功能进行部分专业化-您不能

标签: c++ templates boost


【解决方案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 返回元组,而不是缺点。

如果我正确理解了你的问题

更新:

tuple 继承自 cons。如果参数不是 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&lt;H,T&gt; 的函数。元组函数必须调用 cons 函数。

【讨论】:

  • 不,你被我的例子误导了:元组可以有任意数量的参数。我已将问题中的示例修改为更清楚。据我所知,为任意数量参数的元组创建 push() 的唯一方法是将这种“递归元编程”与 boost::tuples::cons_get_head() 一起使用(返回第一个参数单独)和 boost::tuples::cons_get_tail() (返回一个 cons,其中第一个参数从原始 cons 中删除)
  • 我已经修改了问题来解释为什么我也使用 cons。它可以在没有最通用版本的 push() 的情况下工作。
  • template&lt;typename T, typename HT, typename TT&gt; void push(lua_State* l, T&amp; value, typename boost::enable_if_c&lt;boost::is_base_of&lt;boost::tuples::cons&lt;HT, TT&gt;, T&gt;::value, T&gt;::type=0){ Luaproxy&lt;T&gt;::new_c(l, value, false); } 似乎可以做到,至少可以编译。希望它不会在有效运行中破坏一切。现在,我接受你的回答:)
  • 嗯,好吧,这可能很棘手。你需要 is_tuple 元函数。很快就会看到我的更新
  • 这变得过于复杂了。非常感谢您的努力,但我最终调用了元组版本 pushtuple()。我相信 C++11 和 boost 中的这个模板的东西只不过是 hacks 之上的一大堆 hacks,只是为了保持向后兼容性,而不考虑新手和一般阅读舒适度。我期待着其他编程语言(D?)与这些元编程工具一起诞生,因此更加线性。
猜你喜欢
  • 2022-07-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多