3

プロジェクトの1つにを組み込みたいと思ってluabindいます。そのためには、call_function(以下を参照)と同様に動作する関数を提供する必要があります。この関数は、いくつかのテンプレートマジック(Boostの提供)を使用しており、助けていただければ幸いです。テンプレートメタプログラミングに実際に出くわしたのはこれが初めてであり(それはそれが呼ばれているものですか?)、それで私は少し迷っています。助けていただければ幸いです。

#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n *
#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n

このプリプロセッサビットが何をしているのかよくわかりません。それが何と呼ばれているのかさえわからないので、検索は少し難しいです。Aテンプレートタイプです。私が正しく覚えていれば#a、の文字通りのテキストを挿入しますがa、倍数は何をし#ますか?このプリプロセッサのものの後にこれが来る。

template<class Ret BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A)>
    typename boost::mpl::if_<boost::is_void<Ret>
            , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> >
            , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> > >::type
    call_function(lua_State* L, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) )
    {
        typedef boost::tuples::tuple<BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_TUPLE_PARAMS, _)> tuple_t;
#if BOOST_PP_ITERATION() == 0
        tuple_t args;
#else
        tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a));
#endif

    }

ご覧のとおり、Boostを多用しています。私はグーグルで検索しましBOOST_PP_ITERATIONたが、それでも実際に何をしているのか理解できません。誰かが私に、できればこのコードのコンテキストで、何をしているのBOOST_PPか、そしてそれがどのように引数をに入れるのかを説明してもらえますかargs

私の最終目標はcall_function、自分で定義argsするオーバーロードに渡すことができるコードを生成するコード内を定義することcall_functionです。これは、同じ呼び出し規約を使用できることを意味しますが、を呼び出す前にいくつかの前処理を適用することもできますluabind

この質問は、私が言った方法では非常に具体的ですが、ここで問題がないように、概念が十分に一般的であることを願っています。

4

1 に答える 1

3

BOOST_PP_ *は、プリプロセッサライブラリであるテンプレートメタプログラミングとは関係ありません。名前が示すように、それはプリプロセッサの魔法で動作し、いくつかの本当に頭の痛いことをして、たくさんの同様のテンプレートを生成します。あなたの場合、それは次のようになります。

//preprocessor iteration 0
template<class Ret>
    typename boost::mpl::if_<boost::is_void<Ret>
            , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<> >
            , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<> > >::type
    call_function(lua_State* L, const char* name )
    {
        typedef boost::tuples::tuple<> tuple_t;
        tuple_t args;
    }

//preprocessor iteration 1
template<class Ret , class A0>
typename boost::mpl::if_<boost::is_void<Ret>
        , luabind::detail::proxy_function_void_caller<boost::tuples::tuple<const A0 *> >
        , luabind::detail::proxy_function_caller<Ret, boost::tuples::tuple<const A0 *> > >::type
call_function(lua_State* L, const char* name , const A0 & a0 )
{
    typedef boost::tuples::tuple<const A0 *> tuple_t;
    tuple_t args(&a0);
}

など、他の場所で定義されている最大値まで(たとえばA0, A1, A2, A3... A9、最大値が10の場合)

これ##は、プリプロセッサのトークン連結です。この場合、連結A(またはa)と任意の値n(=> A0、A1、A2、...)があります。コード全体が前処理ループに入っています。

  • BOOST_PP_ITERATION()現在のループインデックス(0、1、2 ...)を示します
  • BOOST_PP_COMMA_IF(X)引数が0でない場合は、コンマを指定します。たとえば、テンプレートパラメータリストの反復1の「クラスA0」の前のコンマ
  • BOOST_PP_ENUM(n,B,C)B(?、N、C)のコンマ区切りリストを提供します。ここで、Nは0 ..(n-1)から実行されます。つまり、マクロBはn回実行されるため、BOOST_PP_ENUM(3、LUABIND_TUPLE_PARAMS、_)を呼び出すと次のようになります。const A0 *, const A1 *, const A2 *
  • BOOST_PP_ENUM_PARAMS(n, X)X##nのコンマ区切りリストを提供します&a0, &a1, &a2BOOST_PP_ENUM_PARAMS(3, &a)

そのプリプロセッサマジックのユースケースの多くは、最近の可変個引数テンプレートを使用して実行できるため、運が良ければ、そのようなものに再び遭遇することはありません;)前処理は他の既知のように機能しないため、一目で把握するのは簡単ではありません。 C ++の機能といくつかの制限があり、回避する必要があるため、理解がさらに難しくなります。

于 2013-01-11T08:09:06.550 に答える