Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I iterate over a vector of functions and call each of them in C++?

I am trying to loop through an array of functions stored in a vector, and i want to call each of them by the iterator pointer object, but something like this:

itr->funcs[i](5); // call the ith index function && pass int 5 as param

is not the solution i guess, what is the solution then ?

Below is my code, please check the last for loop in the code.

#include <iostream>
#include <string>
#include <vector>

// to be able to take other functions as arguments in a function
#include <functional> 

using namespace std;

// receive other functions inside a function
// syntax: return_type function_name(std::function<return_type(parameter_lists)>func_name, parameter_lists)
double doMath(std::function<double(double)> someOtherFunction, double num){
    return someOtherFunction(num);
}

double multBy2(double d){ 
    // b'coz x is pointing to multBy2 the word 'someOtherFunction' in the 
    // above function behaves like an alias for this function 'multBy2'
    return d * 2;
}

double multBy3(double d){
    return d * 3;
}

int main (){
    // dec && init
    auto x = multBy2; // x pointing to multBy2 now
    std::cout << "2 * 5.1 : " << x(5.1) << "\n";
    std::cout << "multBy2 will be called: " << doMath(x, 6.1) << "\n";
    std::cout << "multBy2 will be called, again: " << doMath(x, 6.1) << "\n";

    // store different functions inside a vector

    // you must use the same signature type functions
    std::vector<function<double(double)>> funcs(2);
    funcs[0] = multBy2; // multBy2 stored at the zeroth index
    funcs[1] = multBy3; // multBy3 stored at the first index

    // check
    // funcs[0](10), pass value by index
    std::cout << "2 * 10 = " << funcs[0](10) << "\n";
    std::cout << "3 * 10 = " << funcs[1](10) << "\n";

    // loop through them
    for (auto itr = funcs.begin(); itr != funcs.end(); itr++){
        // iterate through the functions
        // itr->funcs[1](10); // I KNOW THIS IS WRONG, WHAT SHOULD I WRITE HERE?
    }

    return 0;
}
like image 474
questionare_101 Avatar asked Sep 06 '25 05:09

questionare_101


1 Answers

The variable itr is an iterator, which is basically a pointer, i.e. they both point to to an object. In this case the iterator is pointing to a function. You can get to the function by dereferencing itr (much like a pointer) with *itr. Then you can use this object like it's a function (because it is one):

for (auto itr = funcs.begin(); itr != funcs.end(); ++itr)
  (*itr)(10);  // like calling func[i](10)

Since it's an iterator, you might also want to use the -> operator, so that you can use the pointed at object directly. Unfortunately, if you tried to do what might seem like the obvious thing:

itr->(10);  // error

the syntax of the language just doesn't allow it (parentheses can be tricky to figure out, even for a compiler). Fortunately, the language does have a way of allowing you to explicitly say what you mean, which is, "I just want to treat it like a function, so I can call it with ()". There is a function called the call operator which is spelled operator() that you can use. The syntax for that is:

for (auto itr = funcs.begin(); itr != funcs.end(); ++itr)
  itr->operator()(10); 

However, this syntax does seem to defeat the purpose of using the convenient -> operator in the first place.

However, I recommend that you use a range-for loop here (it's usually the better choice if you can use it). The syntax is much clearer at expressing the intent of the code:

for (auto &func : funcs)  // for every function in funcs
   func(10);      // use the function        

Here's a working demo.

like image 148
cigien Avatar answered Sep 07 '25 18:09

cigien