I am curretntly trying to define a namespace/struct which contain function pointers which store a specific implementations (let's say a structure to contain several functions). For now everything works fine with the following structure:
class foo{
int a;
int b;
public:
explicit foo(int _a, int _b) : a(_a), b(_b) {};
std::function<int(int)> bar(int num) = [=](int num) -> int{
// here I need to know a and b
//do something with num and return
}
}
This class contains several functions where each has to know a and b. The problem is that I have to create and instance of the class and set the parameters a and b, which I would rather omit. In another class I use this class only by taking its functions. Namely
class foo2{
//some other parameters
int a, b;
std::function<...> fun1, fun2,...;
public:
foo2(int a, int b, ....){this->a = a; this->b = b;};
setFuncs(){
foo instance(a, b);
this->fun1 = [instance](int num){ return instance.bar(num);}
this->fun2 = ...
}
}
but i want to omit creating a new class inctance each time (in the sense that I repeat the above behavior in the same class but another place in the code). I tried to template this class as
template<int a, int b>
class foo{
...
}
so i could assign the funtions as:
this->fun1 = foo<a,b>::bar;
But then I would need to know a and b at compile time, which is not possible. Those parameters are set once in class foo2. I realise the overall code may not be clean, I'm a physicist, not IT guy, as you can see. One way would be to store an instance of class foo in class foo2 and initialize it once for the whole class and let the functions fun1, fun2,... have access by reference to those pointers, but I 'm looking if there is another way (maybe a template like class, where I don't need to know the values at compile time). Also I can't paste the whole code here as it contains thousands of lines in several files and describing what the code does is very hard. I appreciate any help and apologize if this may be a stupid or trivial question (i don't work in IT strictly, I'm a physicist ;) )
CodePudding user response:
You could create the lambdas in the foo constructor where the values of a and b are known.
Then you could also capture this to use the member variables (in case they change between the lambda creation and the call).
class foo
{
int a;
int b;
public:
// No need for explicit since this isn't a "conversion" constructor
foo(int a, int b) : a(a), b(b)
{
bar = [this](int x)
{
// Use the argument together with this->a and this->b...
return some_value;
};
}
std::function<int(int)> bar;
};
CodePudding user response:
Since you want some input data to stay longer than a single function call, unless it's fully compile-time data a runtime state is inevitable. The question is how you want this data to be encapsulated - different approaches will yield very different (subjective) feelings of how convenient they are.
Based on your usage example:
this->fun1 = foo<a,b>::bar;
If you want to avoid state (or rather encapsulate it) you can create a factory that will create functions for you:
std::function<int(int)> make_func(int a, int b)
{
return [=](int x){ return actual_function(a, b, x); };
}
this->fun1 = make_func(a, b); // now std::function will hold lambda's captured state
This topic is generally known as partial application and I guess boost or other libraries already have a lot of supporting code for such manipulations.
