尝试表达这个问题有点棘手。
所以说我有很多函数,每个函数都有不同数量的参数-有些没有参数,有些只有一个,有些则有几个或更多。我通过矢量接收这些函数的参数。通常,我可以这样称呼他们:
#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
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
错误检查将确保有正确数量的参数,等等。但是,如果我有大量函数,这将变得非常乏味,并且错误检查和我对返回值的处理大部分相同(即检查向量大小与参数个数匹配)。我最终会重复非常相似的〜15行代码100次,并且,如果我决定更改或增加15行“序列”的内容,则必须重做100次。
如果我可以将一个选择映射到一个具有函数指针和我需要的其他信息的数据结构,那将更有意义,那么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
}
}
Run Code Online (Sandbox Code Playgroud)
这个带有“索引技巧”的答案使我非常接近,但是由于它需要unpack_caller常量,因此我不确定如何将其网格划分到我的地图/数据结构中。
首先,这里是funcPointer一个返回lambda std::vector的参数,它在调用给定函数之前先进行-to-arguments杂耍,该函数基于函数的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...>{});
}
Run Code Online (Sandbox Code Playgroud)
然后可以将这些lambda一起存储在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)}
};
Run Code Online (Sandbox Code Playgroud)
最后,调用很简单:
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';
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
73 次 |
| 最近记录: |