【问题标题】:How do I create an std::vector of functions without defining the functions explicitly?如何在不明确定义函数的情况下创建函数的 std::vector?
【发布时间】:2011-12-27 19:04:17
【问题描述】:

我想创建一个 std::vector 对象(或任何其他标准或自定义容器类型),其中包含签名都相同的自定义和任意函数的元素。

应该是这样的:

// Define the functions and push them into a vector
std::vector<????> MyFunctions;
MyFunctions.push_back(double(int n, float f){ return (double) f / (double) n; });
MyFunctions.push_back(double(int n, float f){ return (double) sqrt((double) f) / (double) n; });
// ...
MyFunctions.push_back(double(int n, float f){ return (double) (f * f) / (double) (n + 1); });

// Create an argument list
std::vector<std::pair<int, float>> ArgumentList;
// ...

// Evaluate the functions with the given arguments
// Suppose that it is guarantied that ArgumentList and MyFunctions are in the same size
std::vector<double> Results;
for (size_t i=0; i<MyFunctions.size(); i++)
{
    Results.push_back(MyFunctions.at(i)(ArgumentList.at(i).first, ArgumentList.at(i).second));
}

如果可能,我不想如下明确定义这些函数集:

class MyClass
{
    public:
        void LoadFunctions()
        {
            std::vector<????> MyFunctions;
            MyFunctions.push_back(MyFoo_00);
            MyFunctions.push_back(MyFoo_01);
            MyFunctions.push_back(MyFoo_02);
            // ...
            MyFunctions.push_back(MyFoo_nn);
        }

    private:
        double MyFoo_00(int n, float f) { /* ... */ }
        double MyFoo_01(int n, float f) { /* ... */ }
        double MyFoo_02(int n, float f) { /* ... */ }
        // ...
        double MyFoo_nn(int n, float f) { /* ... */ }
};

使用一些标准库工具(如使用std::function)的实现是可以的。但是,不推荐使用非标准方式(例如使用 BoostQT 或任何其他库或框架)。

【问题讨论】:

    标签: c++ vector functional-programming function-pointers function-call


    【解决方案1】:

    听起来你想要lambda functions。如果你的 C++ 编译器实现了 C++11 标准的这一部分,你可以直接使用它们。否则你也许可以使用Boost PhoenixBoost Lambda

    【讨论】:

    • 自从Boost.Phoenix v3 在 Boost 1.47 中发布后,Boost.Lambda 已被正式弃用。请推荐 Phoenix 的新代码而不是 Lambda。
    • @ildjarn:啊,我不知道。谢谢。
    【解决方案2】:

    假设您的编译器足够现代,您可以使用 C++11 中引入的新 std::function 类型和匿名 (lambda) 函数:

    std::vector<std::function<double(int, float)>> MyFunctions;
    MyFunctions.push_back([](int n, float f) {
        return (double) f / (double) n;
    });
    MyFunctions.push_back([](int n, float f) {
        return (double) sqrt((double) f) / (double) n;
    });
    // ...
    MyFunctions.push_back([](int n, float f) {
        return (double) (f * f) / (double) (n + 1);
    });
    

    【讨论】:

    • 您甚至不必在这里使用function(除非您使用的是VC2010)。无捕获 lambda 优雅地降级为函数指针。但是,使用function 总是很好,以防您想使用函数指针以外的东西。
    【解决方案3】:

    您可以使用 std::function 和 lambdas 来做到这一点:

    #include <vector>
    #include <functional>
    #include <iostream>
    #include <algorithm>
    #include <iterator>
    
    struct dispatcher {
      template <typename F, typename Pair>
      double operator()(const F& func, const Pair& p) const {
        return func(p.first, p.second);
      }
    };
    
    int main() {
      std::vector<std::function<double(int,double)>> functions;
      functions.push_back([](int n, float f) { return double(f)/double(n); });
    
      std::vector<std::pair<int, float>> args = {std::make_pair(1, 10.0f)};
    
      std::vector<double> results;
    
      std::transform(functions.begin(), functions.end(), args.begin(), std::back_inserter(results), dispatcher());
    
      std::copy(results.begin(), results.end(), std::ostream_iterator<double>(std::cout, "\n"));
    }
    

    【讨论】:

      【解决方案4】:

      函数指针就够用了,连std::function:都不需要了

      #include<iostream>
      #include<vector>
      #include<cmath>
      
      int main()
      {
            std::vector<double (*)(double)> vec;
            vec.push_back([](double x) {return cos(x);});
            vec.push_back([](double x) {return sin(x);});
            vec.push_back([](double x) {return tan(x);});
            for (auto f: vec)
                std::cout<<f(M_PI/4)<<'\n';
            return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-23
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 2010-09-19
        • 2015-11-17
        相关资源
        最近更新 更多