可变参数模板索引包扩展
Variadic template indexed pack expansion
假设有以下模板:
template<typename T, bool stack>
struct bind_argument
{
static inline T get_arg(Object& obj, u8 index)
{
return ...;
}
};
template<typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
constexpr bool use_stack = ...;
return function(..., bind_argument<Args, use_stack>::get_arg(obj, 0)...);
}
对于bind_argument我需要传递索引的扩展。 Another question 关于索引扩展展示了 "indices trick" 使用另一个模板的使用,但在我的例子中,我还需要将扩展参数传递给 function[=28= 的调用] 在 调用 方法中。这似乎比我想象的要难很多。
我使用 "indices trick" 的原始解决方案如下所示:
template<bool stack, typename... Args, u64... Indices>
struct bind_arguments
{
static inline Args get_args(CPU& cpu, indices<Indices...>)
{
return bind_argument<Args, stack>(cpu, Indices)...;
}
};
template<typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
constexpr bool use_stack = ...;
Arg0 some_value = ...;
return function(some_value, bind_arguments<use_stack, Args...>::get_args(obj, build_indices<sizeof...(Args)>{}));
}
不幸的是,这不会编译。如何在另一个模板中执行模板索引包扩展,然后将扩展值传递到用于扩展值的位置? (在本例中是 function() 调用)
预期的调用扩展如下:
function(some_value, bind_argument<A1, use_stack>(obj, 0), bind_argument<A2, use_stack>(obj, 1), bind_argument<A3, use_stack>(obj, 2), ...)
你可以在 other 函数中做任何你想做的事情,转发所有必要的参数;没有理由 return 除了最终结果:
#include <utility>
#include <cstddef>
template <typename RT, typename Arg0, typename... Args, std::size_t... Is>
inline RT call(Object& obj, RT(*function)(Arg0, Args...), std::index_sequence<Is...>)
{
return function(&obj, bind_argument<Args>::get_arg(obj, Is)...);
}
template <typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
return call(obj, function, std::make_index_sequence<sizeof...(Args)>{});
}
假设有以下模板:
template<typename T, bool stack>
struct bind_argument
{
static inline T get_arg(Object& obj, u8 index)
{
return ...;
}
};
template<typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
constexpr bool use_stack = ...;
return function(..., bind_argument<Args, use_stack>::get_arg(obj, 0)...);
}
对于bind_argument我需要传递索引的扩展。 Another question 关于索引扩展展示了 "indices trick" 使用另一个模板的使用,但在我的例子中,我还需要将扩展参数传递给 function[=28= 的调用] 在 调用 方法中。这似乎比我想象的要难很多。
我使用 "indices trick" 的原始解决方案如下所示:
template<bool stack, typename... Args, u64... Indices>
struct bind_arguments
{
static inline Args get_args(CPU& cpu, indices<Indices...>)
{
return bind_argument<Args, stack>(cpu, Indices)...;
}
};
template<typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
constexpr bool use_stack = ...;
Arg0 some_value = ...;
return function(some_value, bind_arguments<use_stack, Args...>::get_args(obj, build_indices<sizeof...(Args)>{}));
}
不幸的是,这不会编译。如何在另一个模板中执行模板索引包扩展,然后将扩展值传递到用于扩展值的位置? (在本例中是 function() 调用)
预期的调用扩展如下:
function(some_value, bind_argument<A1, use_stack>(obj, 0), bind_argument<A2, use_stack>(obj, 1), bind_argument<A3, use_stack>(obj, 2), ...)
你可以在 other 函数中做任何你想做的事情,转发所有必要的参数;没有理由 return 除了最终结果:
#include <utility>
#include <cstddef>
template <typename RT, typename Arg0, typename... Args, std::size_t... Is>
inline RT call(Object& obj, RT(*function)(Arg0, Args...), std::index_sequence<Is...>)
{
return function(&obj, bind_argument<Args>::get_arg(obj, Is)...);
}
template <typename RT, typename Arg0, typename... Args>
inline RT call(Object& obj, RT(*function)(Arg0, Args...))
{
return call(obj, function, std::make_index_sequence<sizeof...(Args)>{});
}