将向量解压缩为参数以调用具有可变数量参数的函数 [英] Unpack vector into arguments to call functions that have a variable number of arguments

查看:82
本文介绍了将向量解压缩为参数以调用具有可变数量参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试表达这个问题有点棘手。

It's a little bit tricky trying to phrase this question.

因此,我有很多函数都有不同数量的参数-有些没有,有的有一个,有的有几个或更多。我通过矢量接收这些函数的参数。通常,我可以这样称呼他们:

So let's say I have a large number of functions that all have varying numbers of arguments - some have none, some have one, some have a few or many more. I receive the parameters for these functions in a vector. Normally, I can just call them like this:

 #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行序列的内容,则必须重做100次。

Error checking would be making sure there are the correct number of arguments, etc. But this gets very tedious if I have a large number of functions, and the error checks and what I do with the return value are mostly the same (ie checking that the vector size matches the number of arguments). I end up repeating very similar ~15 lines of code 100 times, and if I ever decide I want to change or add something to that 15 line 'sequence', I'd have to redo it a hundred times.

如果我可以将一个选择映射到一个数据结构,该数据结构包含我需要的函数指针和其他信息,然后再创建my_useful_function,那将更有意义会更像:

It would make more sense if I could make a map from a choice to a data structure that has the function pointer and other information I'll need, and then the my_useful_function would be more like:

 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常量,所以我m不知道如何将其网格化到我的地图/数据结构中。

This answer with the 'index trick' got me really close, but since it requires a constant for the unpack_caller, I'm not sure how to mesh that into my map / data struct.

推荐答案

首先,这里是 funcPointer 会返回一个lambda,该lambda在调用给定函数之前对参数进行 std :: vector 到参数的处理,这是基于函数的Arity生成的:

First, here's funcPointer which returns a lambda doing the std::vector-to-arguments juggling before calling a given function, generated based on the function's 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...>{});
}

这些lambda可以一起存储在 std中:: map< int,std :: function< int(std :: vector&st; std :: string> const&)>>

These lambdas can then be stored together in 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';
    }
}

在Wandbox上实时观看

这篇关于将向量解压缩为参数以调用具有可变数量参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆