[Extensively edited for clarity and typos, and now with attempted solution, old version at the end]
New version of the question
I have a class which needs to store a functor. The problem is that the functor is an expression template (meaning that each functor is of different type). On top of that I need to collect all the objects of that class in a vector.
Below my attempts:
I do not write the code for the functors as expression templates as it is too long. I will therefore test the code by trying to store two functors of two different classes
struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
double operator()(const double x){ return a;}
};
struct FunctorTypeB {
double a, b;
FunctorTypeB(const double ap, const double bp): a(ap), b(bp) {}
double operator()(const double x){ return a+b*x;}
};
I think, correct me if I am wrong, that if the code below works for the two functors above, it should work for any functor constructed with expression templates.
The first idea would be
template <typename functorType> struct myClass {
functorType functor;
myClass(functorType funct): functor(funct){}
};
I can store a functor inside an object of that class with:
FunctorTypeA functor1(1.2);
FunctorTypeB functor2(1.5, 5.0);
myClass myObj1(functor1);
myClass myObj2(functor2);
cout << myObj1.functor(0.2) << " " << myObj1.functor(0.2) << "\n\n";
However I cannot store those objects in an std::vector
as they have different types.
Therefore I tried:
struct myClass2Base {
virtual ~TrialClassBase() = default;
virtual double functor(const double x) = 0;
};
template <typename functorType> struct myClass2 : public myClass2Base {
functorType functorStored;
myClass2(functorType funct): functorStored(funct){}
double functor(const double x){return functorStored(x);}
};
and I can construct a vector of those objects as
std::vector<myClass2Base*> vecOfObj;
vecOfObj.push_back(new myClass2(functor1));
cout << vecOfObj[0]->functor(0.3) << "\n\n";
This one works. Is there a better solution?
Thanks!
Old version of the question
I have a class which needs to store a functor which is an expression template (meaning that each function is of different type). I also need to put the objects of that class in an std::vector.
My Attempt is
struct TrialClassBase{
virtual double get_functor(double) = 0;
};
template <typename derived> struct TrialClass : public TrialClassBase {
derived functor;
TrialClass(derived fun): functor(fun){}
double get_functor(double x) {return functor(x);}
};
std::vector<shared_ptr<TrialClassBase>> vecOfObjs;
Then I try to add an object to the vector. As an example I use an std::function, only as an example: the functor in my case will be an expression template.
std::function<double(double)> funcccc = [](double x){return x*x;};
vecc.emplace_back(TrialClass(funcccc));
cout << vecc[0]->get_functor(0.3) <<"\n\n";
This fails to compile. What mistake am I making? How can I do what I want to do?
Thanks!
I see you have improved your question. Yes there are debatably better solutions.
One nice solution the std lib offers you, is to use type-erasure using std:function
.
#include <vector>
#include <functional>
#include <iostream>
#include <cmath>
struct FunctorTypeA {
double a;
FunctorTypeA(const double ap): a(ap) {}
auto operator()([[maybe_unused]]const double x) const { return a;}
};
int main(){
auto funcVec{std::vector<std::function<double(double)>>{}};
funcVec.push_back(FunctorTypeA{3.14}); // functor allowed
funcVec.push_back([](double x){return x;}); // lambda allowed
funcVec.push_back(sqrt); // function pointer allowed, e.g. C math function
for(auto&& f:funcVec){
std::cout << f(2.0) << '\n';
}
}
This way you don't complicate things with inheritance and pointer casting. Easy to make mistakes there. std::vector
and std::function
will do all the cleaning up. (That was something you can easily miss in your vector-of-pointers solution)
Note: std::function
may perform a dynamic allocation. But so does std::vector
and inheritance has vtable overhead.