c++ - 将向量解包到参数中以调用具有可变数量参数的函数
问题描述
试图表达这个问题有点棘手。
所以假设我有大量的函数,它们都有不同数量的参数——有些没有,有些只有一个,有些有几个或更多。我在向量中接收这些函数的参数。通常,我可以这样称呼他们:
#include <vector>
int my_functionA(std::string a) { /*...*/ return 1; }
int my_functionB(std::string a, std::string b) { /*...*/ return 2; }
void some_useful_function(std::vector<std::string> vec, int choice) {
if (choice == 1) {
// Error checking would happen here
int val = my_functionA(vec[0]);
// Do something with val
// ...
}
else if (choice == 2) {
// Error checking would happen here
int val = my_functionB(vec[0], vec[1]);
// Do something with val
// ...
}
}
错误检查将确保有正确数量的参数等。但是如果我有大量函数,这会变得非常乏味,并且错误检查和我对返回值所做的事情几乎相同(即检查向量大小与参数的数量相匹配)。我最终将非常相似的约 15 行代码重复了 100 次,如果我决定要更改或添加一些东西到这 15 行“序列”,我将不得不重做一百次。
如果我可以将选择映射到具有函数指针和我需要的其他信息的数据结构,那会更有意义,然后 my_useful_function 会更像:
struct funcPointer {
funcPointer(void * f, int n) : fnc(f), numOfArgs(n) {};
void * fnc;
int numOfArgs;
};
std::map<int, funcPointer> = {
{1, funcPointer(my_functionA, 1)},
{2, funcPointer(my_functionB, 2)}};
void some_useful_function(std::vector<std::string> vec, int choice) {
if (map.count(choice) > 0) {
// Do stuff if map[choice].numOfArgs doesn't match vec size
int val = map[choice].fnc(vectorSomehowConvertedToArguments);
// Do stuff with the return value
}
}
这个带有“索引技巧”的答案让我非常接近,但由于它需要 unpack_caller 的常量,我不确定如何将其网格化到我的地图/数据结构中。
解决方案
首先,这是在调用给定函数之前funcPointer
返回一个执行 -to-arguments 杂耍的 lambda std::vector
,它是根据函数的 arity 生成的:
template <class F, std::size_t... ParamsIdx>
auto funcPointer(F f, std::index_sequence<ParamsIdx...>) {
return [f](std::vector<std::string> const &args) {
assert(args.size() == sizeof...(ParamsIdx));
return f(args[ParamsIdx]...);
};
}
template <class... Params>
auto funcPointer(int (*f)(Params...)) {
return funcPointer(f, std::index_sequence_for<Params...>{});
}
然后可以将这些 lambdas 一起存储在 a 中std::map<int, std::function<int(std::vector<std::string> const &)>>
:
std::map<int, std::function<int(std::vector<std::string> const &)>> map = {
{1, funcPointer(my_functionA)},
{2, funcPointer(my_functionB)}
};
最后,调用很简单:
void some_useful_function(std::vector<std::string> vec, int choice) {
if (map.count(choice) > 0) {
int val = map[choice](vec);
// Do stuff with the return value
std::cout << "Call succeeded, got " << val << '\n';
}
}
推荐阅读
- netsuite - suitescript 在单击按钮时运行函数
- ios - 如何根据 Childviewcontroller(UIViewController 的不同大小)高度更改容器视图(父视图)的高度?
- macos - Mac OSX - 常用命令不起作用
- c# - 更新数据库记录在 c# winforms 和 MSAccess 中不起作用
- google-chrome - 为什么 Chrome 会错误地为我的 JSF 页面资源编写 URL?
- c++ - 如何使用 CImg 加载图像的 CImg 检索色彩空间?
- c# - 通过 PreSignedURL 访问 AWS S3 上的文件时出现异常
- php - 使用带有 codeigniter 的 smtp 向 2 个具有不同消息的收件人发送电子邮件
- xml - 如何可视化 DocBook 文件?
- fullcalendar - 使用 FullCalendar 想要在事件 A 更改时更改事件 B 的属性