创建数据元组并将unpacked作为函数参数发送

时间:2014-11-07 21:54:23

标签: c++ templates metaprogramming variadic stdtuple

嗨我很想知道是否有人可以帮助我。我正在尝试实现CallFunction(带注释的位)。我不知道该怎么做。

[问题]我想创建一个由...参数创建的类型元组,但我想 剥离限定符,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}
};

1 个答案:

答案 0 :(得分:1)

我假设,您的意思是使用相应的索引分配值,而不是始终分配给循环内的0索引。假设你有std::integer_sequence的实现(这是C ++ 14的一部分),使用std::tuple<...>元素调用函数的基本方法是相当直接的:

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<...>创建一个合适的整数序列。完成此操作后,您还可以添加相应的操作,并使用基于std::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实现相应的类。实施相当直接。 Here is an implementation使用不同的名称实现必要的整数生成。