C++ C++;可变模板和求值顺序

C++ C++;可变模板和求值顺序,c++,templates,variadic-templates,C++,Templates,Variadic Templates,我有以下代码: lib.hxx: template <typename C, typename R, typename ... Args> R Lib::extract_call(lua_State* L, R(C::*method)(Args...)) { return static_cast<C*>(this)->*method(extract_data<Args>(L)...); } 如果可以将方法更改为采用单个std::tuple,而不是多

我有以下代码:

lib.hxx:

template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
  return static_cast<C*>(this)->*method(extract_data<Args>(L)...);
}

如果可以将方法更改为采用单个
std::tuple
,而不是多个
Args…
,则可以将
extract\u data
放在大括号初始化器中:

return static_cast<C*>(this)->*method({extract_data<Args>(L)...});
返回static_cast(this)->*方法({extract_data(L)…});

与函数参数不同,初始化器子句的求值顺序是从左到右。

现在我们将得到更复杂的模板。以下代码是我在没有编译器的情况下编写的,可能有一些错误:

template <unsigned int n>
class tuple_extractor{
    template <typename T, typename ...ArgsOut, typename ...ArgsIn, typename ...ArgsPart>
    static void extractTuple(
            T* obj,
            void (T::*func)(ArgsOut...),
            const std::tuple<ArgsIn...>& inParams,
            ArgsPart... partParams){
        tuple_extractor<n-1>::extractTuple(obj, func, inParams, std::get<n-1>(inParams));
    }
};

template <>
class tuple_extractor<0>{
    template <typename T, typename ...ArgsOut, typename ...ArgsIn>
    static void extractTuple(
            T* obj,
            void (T::*func)(ArgsOut...),
            const std::tuple<ArgsIn...>& inParams,
            ArgsIn... partParams){
        obj->func(partParams...);
    }
};

template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
    std::tuple<Args...> tmp{extract_data<Args>(L)...};
    tuple_extractor<sizeof...(Args)>::extractTuple(static_cast<C*>(this), method, tmp);
}
模板
类元组提取器{
模板
静态空抽取元组(
T*obj,
void(T::*func)(ArgsOut…),
const std::影响大括号初始化顺序的元组。若使用受影响的版本,只需使用

// For first-to-last order use:
template <typename T, typename ...Args>
inline std::tuple<T, Args...> getTuple(lua_State* L){
    return std::tuple_cat(std::make_tuple<T>(extract_data<T>(L)), getTuple<Args...>(L));
}

template <typename T>
inline std::tuple<T> getTuple(lua_State* L){
    return std::make_tuple<T>(extract_data<T>(L));
}

    template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
    std::tuple<Args...> tmp = getTuple<Args...>(L);
    tuple_extractor<sizeof...(Args)>::extractTuple(static_cast<C*>(this), method, tmp);
}
//对于从第一个订单到最后一个订单的使用:
模板
内联std::tuple getTuple(lua_State*L){

返回std::tuple_cat(std::make_tuple(extract_data(L)),getTuple:

问题是-他能做到吗?也许调用的函数是他无法控制的某个API的一部分?@j_kubik:的确。如果你不能更改它,那么你就不能这样做。我没有测试你的代码,但这正是我在考虑递归模板时想要得到的,而没有实现可用的东西。我仍然存在一个问题但在我的情况下:参数需要从lua堆栈中以还原顺序提取,我认为这是不可能的…我无法编译您的代码,即使在进行了一些修复之后,模板错误变得如此粗鲁,我放弃了。我改为非可变模板来解决我的问题。当我有时间时,我可能会尝试将其编译为ble,而且我很确定也可以使用反向顺序。反向计算实际上相当简单-在提取参数之前只需调用递归案例。复杂的原因在于需要收集返回值。您可以使用
std::tuple
轻松完成此操作,不过:。最终解包到调用中可以我用一个字母完成了。
template <unsigned int n>
class tuple_extractor{
    template <typename T, typename ...ArgsOut, typename ...ArgsIn, typename ...ArgsPart>
    static void extractTuple(
            T* obj,
            void (T::*func)(ArgsOut...),
            const std::tuple<ArgsIn...>& inParams,
            ArgsPart... partParams){
        tuple_extractor<n-1>::extractTuple(obj, func, inParams, std::get<n-1>(inParams));
    }
};

template <>
class tuple_extractor<0>{
    template <typename T, typename ...ArgsOut, typename ...ArgsIn>
    static void extractTuple(
            T* obj,
            void (T::*func)(ArgsOut...),
            const std::tuple<ArgsIn...>& inParams,
            ArgsIn... partParams){
        obj->func(partParams...);
    }
};

template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
    std::tuple<Args...> tmp{extract_data<Args>(L)...};
    tuple_extractor<sizeof...(Args)>::extractTuple(static_cast<C*>(this), method, tmp);
}
// For first-to-last order use:
template <typename T, typename ...Args>
inline std::tuple<T, Args...> getTuple(lua_State* L){
    return std::tuple_cat(std::make_tuple<T>(extract_data<T>(L)), getTuple<Args...>(L));
}

template <typename T>
inline std::tuple<T> getTuple(lua_State* L){
    return std::make_tuple<T>(extract_data<T>(L));
}

    template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
    std::tuple<Args...> tmp = getTuple<Args...>(L);
    tuple_extractor<sizeof...(Args)>::extractTuple(static_cast<C*>(this), method, tmp);
}