Search code examples
c++vectorfunctional-programmingfunction-pointersfunction-call

How do I create an std::vector of functions without defining the functions explicitly?


I want to create an std::vector object (or any other standard or custom container type) with elements of custom and arbitrary functions whose signatures are all the same.

It should be something like this:

// 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));
}

If possible, I don't want to define these set of functions explicitly as below:

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) { /* ... */ }
};

An implementation with some standard library tool (like using std::function) is OK. But, a non-standard way of doing this (like using Boost, QT or any other library or framework) is not preferred.


Solution

  • Assuming your compiler is modern enough, you can use the new std::function type and anonymous (lambda) functions introduced in C++11:

    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);
    });