Obs*_*ian 4 c c++ variadic stack-frame
我正在重构一个 C++ 应用程序,它引用了一堆多个回调函数,每个回调函数都有不同数量的参数,我想知道在调用每个函数之前是否有一种通用的方法来构建专用的参数堆栈框架。
换句话说:首先根据要调用的函数获取所有必需的参数,然后执行对被调用函数透明的调用。
在某种程度上,这与可变参数函数相反,因为这将是一个知道它可以接收不同数量参数的单个函数。在这里,我有一堆不可变的常规函数,我想从通用集线器调用它们。
我把C和C++标签都放在这里是因为我对这两种语言的命题都很感兴趣,我觉得适用于 C 的东西也适用于 C++,我仍然对“仅限 C++”的解决方案持开放态度,例如可变参数模板等。
所有这一切的背景是引用的程序实际上是在解析命令行,然后根据命令的名称调用函数,作为程序名称后的第一个参数传递,然后所有必需的作为纯字符串,但取决于调用的命令.
我知道我可以写这样的东西:
if(nb_of_args == 1)
my_callback_ptr(argv[n]);
else if (nb_of_args == 2)
my_callback_ptr(argv[n],argv[n+1]);
else if (nb_of_args == 3)
my_callback_ptr(argv[n],argv[n+1],argv[n+2]);
else if (nb_of_args == 4)
my_callback_ptr(argv[n],argv[n+1],argv[n+2],argv[n+3]);
else if…
Run Code Online (Sandbox Code Playgroud)
...无论函数本身如何,将编译调用限制为唯一数量的参数,但我仍然希望做得更好。
在此先感谢大家。
一种可行的方法是实现调度表,该表将包含指向包装函数的指针,自动将适当数量的参数传递给每个回调。
#include <array>
#include <utility>
#include <cstddef>
template<auto x_p_callback, ::std::size_t... x_indexes>
void invoke_callback(char const * const * const pp_args, ::std::index_sequence<x_indexes...>)
{
(*x_p_callback)(pp_args[x_indexes]...);
}
template<typename x_Callback >
struct
t_ArgsCount;
template<typename x_Result, typename... x_Args>
struct
t_ArgsCount<x_Result (x_Args...)>
: ::std::integral_constant<::std::size_t, sizeof...(x_Args)>
{};
template<auto x_p_callback>
void callback_sunk(char const * const * const pp_args)
{
using
t_Callback = typename ::std::remove_reference<decltype(*x_p_callback)>::type;
using
t_Sequence = typename ::std::make_index_sequence<t_ArgsCount<t_Callback>::value>;
invoke_callback<x_p_callback>(pp_args, t_Sequence{});
}
using
t_Callback = void (char const * const * const pp_args);
template<auto... x_p_callbacks>
constexpr auto make_table(void)
{
return ::std::array<t_Callback *, sizeof...(x_p_callbacks)>{&callback_sunk<x_p_callbacks>...};
}
void my_callback_0() {}
void my_callback_1(char const *) {}
void my_callback_2(char const *, char const *) {}
void my_callback_3(char const *, char const *, char const *) {}
int main(int argc, char const * const * const pp_args)
{
constexpr auto table{make_table<my_callback_0, my_callback_1, my_callback_2, my_callback_3>()};
table.at(argc)(pp_args);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |