Как я могу перебрать вектор функций и вызвать каждую из них в C ++? - PullRequest
2 голосов
/ 01 мая 2020

Я пытаюсь l oop через массив функций, хранящихся в векторе, и я хочу вызвать каждую из них с помощью объекта указателя итератора, но что-то вроде этого:

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

is не решение, я думаю, что решение тогда?

Ниже мой код, пожалуйста, проверьте последний для l oop в коде.

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

1 Ответ

8 голосов
/ 01 мая 2020

Переменная itr является итератором, который в основном является указателем, т.е. они оба указывают на объект. В этом случае итератор указывает на функцию. Вы можете получить к функции разыменование itr (очень похоже на указатель) с *itr. Затем вы можете использовать этот объект как функцию (потому что она одна):

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

Поскольку это итератор, вы также можете использовать оператор ->, чтобы вы могли использовать указанную на объекте напрямую. К сожалению, если вы попытались сделать то, что может показаться очевидным:

itr->(10);  // error

, синтаксис языка просто не позволяет этого (скобки могут быть сложными, даже для компилятора). К счастью, в языке есть способ, позволяющий вам явно сказать, что вы имеете в виду, а именно: «Я просто хочу рассматривать это как функцию, поэтому я могу вызывать ее с помощью ()». Существует функция под названием оператор вызова , которая пишется operator(), которую вы можете использовать. Синтаксис для этого:

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

Тем не менее, этот синтаксис, по-видимому, лишает цели использования удобного оператора ->.

Однако я рекомендую вам используйте диапазон для l oop здесь (обычно это лучший выбор, если вы можете его использовать). Синтаксис намного яснее при выражении намерений кода:

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

Вот рабочая демо .

...