Search code examples
c++functiontemplatesstructlambda

How can I get the return of a function called from a vector std::vector that contains std::function


I have a structure that in its constructor receives an initialization list std::initializer_list<P...> of type parameter pack. That constructor is filled with lambda functions, and they are saved in a std::vector<P...>.

How can I get the return of those functions when traversing the vector calling each function?

Here is an example of the structure and what I want to do:

#include <iostream>
#include <functional>
#include <initializer_list>
using namespace std;

struct my_type {
    my_type(){}
    my_type(string _value) : value(_value) {}
    string value = "test";
    string getValue(){return value;}
};


template<typename A, class...P>
struct struct_name {
  struct_name(std::initializer_list<P...> list)  : functions(list) {}
  std::vector<P...> functions;
  
  string value;
  my_type type;      

  string execute_functions(){
     for (size_t i = 0; i < functions.size(); i++)
    {
     value = functions[i](type);  // something like this, this does not work
    }
    return value;
    std::cout << value;
  }
};

typedef struct_name<std::function<void(my_type)>, std::function<void(my_type)>> _functions;


int main(int argc, char const *argv[])
{

    _functions object = {
      [](my_type var)->string{
        return var.getValue();
      },
      [](my_type var)->string{
        return var.getValue();
      },
    };

    return 0;
}

Everything works perfect except the way to obtain those values. I don't know how, and no matter how hard I look I can't find answers.

EDIT: I can't paste the complete code, because it depends on many other classes. I tried to recreate that section, the type is a parameter pack because it receives multiple types besides lambdas, but in the example I just put it that way.


Solution

  • You should be using std::tuple, if you want to store arbitrary callable objects.

    You can combine std::index_sequence with a fold expression for calling the functions:

    #include <iostream>
    #include <string>
    #include <tuple>
    #include <utility>
    
    using std::string;
    
    struct my_type {
        my_type(){}
        my_type(string _value) : value(_value) {}
        string value = "test";
        string getValue(){return value;}
    };
    
    template<class...P>
    struct struct_name {
        struct_name(P... args)
            : functions(args...)
        {}
    
        std::tuple<P...> functions;
    
        std::string value;
        my_type type;
    
        std::string execute_functions() {
            return execute_helper(std::make_index_sequence<sizeof...(P)>{});
        }
    private:
        template<size_t ...Is>
        std::string execute_helper(std::index_sequence<Is...>)
        {
            ((value += std::get<Is>(functions)(type)), ...);
            return value;
        }
    };
    
    int main()
    {
        struct_name foo(
            [](my_type var)->string {
                return var.getValue();
            },
            [](my_type var)->string {
                return var.getValue();
            });
        std::cout << foo.execute_functions() << '\n';
        return 0;
    }