繁体   English   中英

将向量解压缩为参数以调用具有可变数量参数的函数

[英]Unpack vector into arguments to call functions that have a variable number of arguments

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

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

 #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次。

如果我可以将一个选择映射到一个具有函数指针和我需要的其他信息的数据结构,那将更有意义,那么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 ,它返回一个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...>{});
}

然后可以将这些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)}
};

最后,调用很简单:

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上实时观看

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM