有没有办法调用具有不同数量变量的函数?

Is there a way to call a function with different number of variables?

我想设计一种方法来调用许多非常相似的函数之一——唯一的区别是参数的数量。请记住,这是我更大问题的一个最小例子。我有很多功能可以完成不同的任务。每个函数原型都非常相似 - 除了它们具有不同数量的参数。

我希望能够调用一些包装器 class,我告诉它测试类型并传递给它一个参数列表(向量),它会为我整理其余部分。

这是一个工作设置(不工作的部分被注释掉):

#include <vector>
#include <map>
#include <functional>
#include <iostream>

enum class test_type {t0, t1, t2, t3, t4, tn};

class tester
{
public:
    void run(test_type type, const std::vector<int> &args)
    {
        func_map[type].func();
    };

private:    
    void function_0()                       { std::cout << "f0\n"; };
    void function_1(int p1, int p2)         { std::cout << "f1\n"; };
    void function_2(int p1, int p2, int p3) { std::cout << "f2\n"; };
    void function_3(int p1, int p2)         { std::cout << "f3\n"; };
    void function_4(int p1)                 { std::cout << "f4\n"; };
    void function_n(int p1)                 { std::cout << "fn\n"; };


    struct test_info
    {
        std::function<void()> func; // variadic function std::function<void(...)> ?
        int num_params;
    };

    std::map<test_type, test_info> func_map {
        {test_type::t0, {[this]{function_0();}, 0}}
        // {test_type::t1, {[this]{function_1();}, 2}}
        // {test_type::t2, {[this]{function_2();}, 3}}
        // {test_type::t3, {[this]{function_3();}, 2}}
        // {test_type::t4, {[this]{function_4();}, 1}}
        // {test_type::tn, {[this]{function_n();}, 1}}
    };
};

int main() {

    tester test;
    test.run(test_type::t0, {});
    //test.run(test_type::t1, {1, 2});
    //test.run(test_type::t2, {1, 2, 3});
    //test.run(test_type::t3, {1, 2});
    //test.run(test_type::t4, {1});
    //test.run(test_type::tn, {1});

    return 0;
}

所以这是有效的,因为 function_0 有 0 个参数,因此匹配 std::function<void()> 类型。我不太确定从这里开始的最佳方向是什么。

认为 有一个使用可变参数的选项 std::function<void(...)> 但是阅读这个让我超出了我的舒适区并且我对可变参数模板的理解不是很好.

所以我的问题是:

vector 本身传递给包装器 lambda,并让它们提取 int 值以传递给它们的目标函数,例如:

#include <vector>
#include <map>
#include <functional>
#include <iostream>
#include <stdexcept>

enum class test_type {t0, t1, t2, t3, t4, tn};

class tester
{
public:
    void run(test_type type, const std::vector<int> &args)
    {
        func_map[type](args);
    };

private:    
    void function_0()                       { std::cout << "f0\n"; };
    void function_1(int p1, int p2)         { std::cout << "f1\n"; };
    void function_2(int p1, int p2, int p3) { std::cout << "f2\n"; };
    void function_3(int p1, int p2)         { std::cout << "f3\n"; };
    void function_4(int p1)                 { std::cout << "f4\n"; };
    void function_n(int p1)                 { std::cout << "fn\n"; };

    static void validate(const std::vector<int> &args, size_t needed) {
        if (args.size() != needed)
            throw std::invalid_argument("wrong number of arguments");
    }

    using func_type = std::function<void(const std::vector<int> &)>;

    std::map<test_type, func_type> func_map {
        {test_type::t0,
          [this](const std::vector<int> &args){
            validate(args, 0);
            function_0();
          }
        },
        {test_type::t1,
          [this](const std::vector<int> &args){
            validate(args, 2);
            function_1(args[0], args[1]);
          }
        },
        {test_type::t2,
          [this](const std::vector<int> &args){
            validate(args, 3);
            function_2(args[0], args[1], args[2]);
          }
        },
        {test_type::t3,
          [this](const std::vector<int> &args){
            validate(args, 2);
            function_3(args[0], args[1]);
          }
        },
        {test_type::t4,
          [this](const std::vector<int> &args){
            validate(args, 1);
            function_4(args[0]);
          }
        },
        {test_type::tn,
          [this](const std::vector<int> &args){
            validate(args, 1);
            function_n(args[0]);
          }
        },
    };
};

int main() {

    tester test;
    test.run(test_type::t0, {});
    test.run(test_type::t1, {1, 2});
    test.run(test_type::t2, {1, 2, 3});
    test.run(test_type::t3, {1, 2});
    test.run(test_type::t4, {1});
    test.run(test_type::tn, {1});

    return 0;
}

Live Demo