2011-12-31 19 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); 
} 

私は2番目の引数としてboost::make_tuple(...)の結果を渡されたときに呼び出さpush()boost::tuples::consバージョンを見ることを期待します。しかし、そのような呼び出しがpushの最も一般的なバージョン、つまりpush(lua_State* l, T& value)に解決されていることを示すリンクにはエラーが発生します。

最終結果は私が

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

を行うことができなければならないということであり、私は私のpush()機能の最も一般的な形式、の残りの部分を削除した場合、これは順番に

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) 

を呼び出す必要があります引数としてtypleを使用してpush()を呼び出す私のアプリケーションのコードは、関数の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:注:テンプレート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 &、 typename boost :: disable_if、T>、T> :: type *) /home/pisto/sorgenti/hopmodv4/src/hopmod/lua/push_function.hpp:56:6:テンプレートvoid lua :: push(lua_State *、constのブースト::タプル::短所&)

+1

あなたは関数の部分的な特殊化をしようとしているようです - – Anycorn

答えて

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

はリターンが、ない短所をタプルmake_tuple

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

予告する必要があります。私はあなたの質問を理解している場合

正しく

更新:

タプルは短所を継承しています。あなたがしなければならないのは、議論が議論の派生でなく、それが可能ならば、一般的なテンプレートに失敗することです。

あなたが道にする必要がありますしようと何を見て:

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()(最初の引数が最初のコンスからはずされてコンスを返します) –

+0

私はコンスもなぜ使用しているのかを説明するために質問を修正しました。それはpush()の最も一般的なバージョンなしで動作します。 –

+0

ok、ありがとう、2回目の更新を参照してください。 – Anycorn

関連する問題