I have a structure that in the 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...> point is how I get the return of those functions when traversing the vector calling each function here I leave 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 totally don't know 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 and I tried to recreate that section, the type is parameter pack because it receives multiple types besides lambdas but in the example I just put it that way
CodePudding user response:
If you are trying to process a value through a series of function you can just use std::accumulate
:
#include <iostream>
#include <vector>
#include <functional>
#include <numeric>
int main()
{
std::vector<std::function<float(float)>> functions = {
[] (float f) { return f*f; },
[] (float f) { return f 2; }
};
float result = std::accumulate(functions.begin(), functions.end(), 1.5f,
[] (float v, const auto& lambda) {
return lambda(v);
}
);
std::cout << 1.5f << " -> " << result << std::endl;
return 0;
}
But a vector can only contain one specified type, so what you are trying to do with you parameter pack P...
doesn't make much sense, if you want to process multiple values through multiple functions with different signatures you'd better try with something like std::tuple<std::function<T1(T2)>, std::function<T3(T4)>, ...>
and pass multiple values to it.
CodePudding user response:
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;
}