有什么方法可以调用一个变量数不同的函数?

问题描述 投票:0回答:1

我想设计一种方法来调用许多非常相似的函数中的一个--其中唯一不同的是参数的数量。请记住,这只是我的大问题的一个最小的例子。我有很多函数用于完成不同的任务。每个函数的原型都非常相似--除了它们的参数数量不同。

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

下面是一个可行的设置(不可行的部分被注释掉)。

#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()> 型。我真的不知道从这里出发的最佳方向是什么。

I 认为 有一个选项可以使用变量 std::function<void(...)> 但读了这本书后,我超出了我的理解范围,而且我对可变模板的理解也不是很好。

所以我的问题是。

  • 这可以用varidic来做吗?std::funtion<void(...)> 在某种程度上?
  • 有没有更好的方法来实现这个目标?
c++ c++11 templates std-function
1个回答
1
投票

传递 vector 本身的包层,并让他们提取出的 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;
}

现场演示

© www.soinside.com 2019 - 2024. All rights reserved.