0

こんにちは、誰かが私を助けてくれるかどうか疑問に思っていました。CallFunction (コメントが入っているビット) を実装しようとしています。どうすればいいのかわかりません。

[質問] ...Arguments から作成された型のタプルを作成したいのですが、修飾子、const、& などを削除したいので、データを入力して関数に渡すことができます。 .

今のところ、戻り値の型は気にしません。誰かが私を正しい方向に向けるか、似たようなことをしましたか? それとも、完全にクレイジーで、できることではないのでしょうか。うーん!とにかくそれをチェックするためのTY :)

template <typename This, typename Func> class ForwardFunction
{
private:
    template <typename Object, typename Return, typename ...Arguments> struct info_base
    {
        enum { nargs = sizeof...(Arguments) };

        typedef Return return_type;
        typedef std::tuple<Arguments...> arg_list_type;

        template <size_t index> struct arg
        {
            typedef typename std::tuple_element<index, std::tuple<Arguments...>>::type type;
        };

        template <int argCount> static void CallFunction(Func function, CLuaHelper & helper, lua_State *pState)
        {
            /*
            // temp - pseudo

            arg_list_type argList;

            for (int i = 0; i < argCount; ++i)
                std::get<0>(argList) = helper.Get<arg<i>::type>(pState);

            (This::GetThis(pState)->*(function))(argList...);
            */
        }

        template <> static void CallFunction<0>(Func function, CLuaHelper & helper, lua_State *pState)
        {
            (This::GetThis(pState)->*(function))();
        }

        static void Call(Func function, CLuaHelper & helper, lua_State *pState)
        {
            CallFunction<nargs>(function, helper, pState);
        }
    };

    template <typename Func> struct info;
    template <typename Object, typename Return, typename ...Arguments> struct info<std::function<Return (Object::*)(Arguments...)>> : info_base<Object, Return, Arguments...> { };
    template <typename Object, typename Return, typename ...Arguments> struct info<std::function<Return (Object::*)(Arguments...) const>> : info_base<Object, Return, Arguments...> { };

public:
    static int ForwardCall(Func function, lua_State *pState)
    {
        CLuaHelper helper(pState);
        info<std::function<Func>>::Call(function, helper, pState);
        return helper.ReturnValues();
    }
};

その使用

#define __LUA_FUNCTION_CALL [&](lua_State *pState) -> int

#define __LUA_INSTANT_ACCESS_CALL(name) \
    { #name, __LUA_FUNCTION_CALL { return ForwardFunction<CComponentScript, decltype(&CComponent::##name)>::ForwardCall(&CComponent::##name, pState); } }

const CLuaHelper::function_list CComponentScript::m_sRegisterFunctions[] =
{
    __LUA_INSTANT_ACCESS_CALL(SetOnLoad),
    __LUA_INSTANT_ACCESS_CALL(SetOnEvent),
    __LUA_INSTANT_ACCESS_CALL(SetOnUpdate),
    __LUA_INSTANT_ACCESS_CALL(SetOnClose),

    __LUA_INSTANT_ACCESS_CALL(RegisterEvent),

    __LUA_INSTANT_ACCESS_CALL(SetBasePriority),

    {nullptr, nullptr}
};
4

1 に答える 1

1

0ループ内で常にインデックスに割り当てるのではなく、対応するインデックスに値を割り当てることを意味していると思います。a の要素を使用して関数を呼び出す基本的なアプローチは、 (C++14 の一部である)std::tuple<...>の実装があると仮定すると、かなり簡単です。std::integer_sequence

template <int... N, typename... T>
void call_aux(std::integer_sequence<int, N...>, std::tuple<T...>&& value)
{
    print(std::get<N>(value)...);
}

template <typename Tuple>
void call(Tuple&& value)
{
    call_aux(std::make_integer_sequence<int, std::tuple_size<std::decay_t<Tuple>>::value>(),
             std::forward<Tuple>(value));
}

基本的な考え方はstd::make_integer_sequence<...>、適切な整数のシーケンスを作成することです。これを取得したら、対応する操作を追加して、 astd::tuple<...>に基づいた値を入力することもできますpState。実際に埋めるロジックは次のstd::tuple<...>ようになります (Lua をインストールしていません。つまり、これが実際に機能するかどうかをテストすることはできませんが、このようなものは機能します)。

template <int I, typename Tuple>
bool assign_helper2(Tuple& tuple, lua_Helper& helper, lua_State* pState) {
    std::get<I>(tuple) = helper.Get<arg<I>::type>(pState);
}
template <typename... T>
void dummy(T&&...) {
}
template <int I, typename Tuple>
void assign_helper1(std::integer_sequence<int, I...>, Tuple& tuple,
                    lua_Helper& helper, lua_State* pState) {
    dummy(assign_helper2<I>(tuple, helper, pState)...);
}
template <typename Tuple>
void assign(Tuple& tuple, lua_Helper& helper, lua_State* pState) {
    assign_helper1(std::make_integer_sequence<int, std::tuple_size<std::decay_t<Tuple>>::value>(),
                   tuple, helper, pState);
}

コードは C++14 の機能を使用していますが、対応するクラスは C++11 を使用して実装できます。実装はかなり簡単です。ただし、異なる名前を使用して必要な整数生成を実装する実装を次に示します。

于 2014-11-07T22:15:36.163 に答える