Reputation: 1070
I have a class in which I need a function that I can define per object. I wish to be able to define each object's specific function while defining a vector of said objects. These vectors of my object are going to make up part of a library. Here is an unsuccessful example of what I am trying to do:
#include <iostream>
#include <vector>
class FunctionEater {
public:
virtual double func() {}
FunctionEater(double (*Func)) {
func = Func; // Not sure of the correct syntax here
}
};
std::vector<FunctionEater> gorgers {
{
double () { // Not sure of the syntax here, or if there is even syntax to do this
double result = 0.794 * 739.775;
return result;
}
},
{
double () {
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
}
}
}
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
So, the two things I'm struggling to figure out, or find much documentation about, are as follows:
I would prefer to be able to define the function within the object definition. I have spent a fair bit of time working out how best to write my vector of objects, and the way that is most visually easy to work with in this situation, seems to be defining every aspect of each object in one block, while defining the vector they are contained in.
I will admit, I also don't know if (*Func) is correct while using a virtual function, but this is an adaptation from my first attempt using function pointers. I am also happy to accept alternative suggestions that might work better than the method I am trying to use.
Thanks in advance for any assistance you can offer, and I am happy to edit or update my question if necessary.
Pete
Upvotes: 0
Views: 58
Reputation: 4715
What you want is better functional features support from your language. Luckily, you are using c++!
After c++11, we have lambdas and std::function
objects which represent runtime polymorphic function objects.
A lambda is defined like this:
auto yourSecondFunc = [](){
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
};
I've been lazy and used auto there, but actually, we could assign it to an std::function
object:
std::function<double()> yourSecondFunc = [](){
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
};
That std::function<double()>
means, the function takes no argument and returns a double. However note that the type of the lambda is not an std::function
object but it is not the place to discuss it.
So, you can store a std::function<double()>
in your FunctionEater
class:
class FunctionEater {
public:
std::function<double()> func;
FunctionEater(const std::function<double()>& f) {
func = f;
}
void callMe() { double res = func(); } // how a function object is used
};
Then, your vector becomes this:
std::vector<FunctionEater> gorgers {
FunctionEater { []()
{
double result = 0.794 * 739.775;
return result;
}
},
FunctionEater { []()
{
double temp1 = 0.794 * 739.775;
double result = temp1 + 0.62;
return result;
}
}
};
And your main
? It actually is the same:
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
Upvotes: 2
Reputation: 141554
The proper syntax is:
#include <iostream>
#include <vector>
#include <functional>
struct FunctionEater
{
using Func = double (*)();
//using Func = std::function<double()>;
template<typename F>
FunctionEater(F f): func(f) {}
Func func;
};
std::vector<FunctionEater> const gorgers = {
[]{ return 0.794 * 739.775; },
[]{ return 0.794 * 739.775 + 0.62; }
};
int main()
{
double snackCrumbs = gorgers[0].func();
double gorgePoop = gorgers[1].func();
std::cout << snackCrumbs << std::endl << gorgePoop << std::endl;
}
You can use either definition of Func
. The function pointer has less overhead but it can only work with a capture-less lambda. The std::function
is much more flexible.
NB. I'm not sure why the vector initialization doesn't work without a template constructor for FunctionEater, but I found that in that case the vector initializers had to be explicitly converted (either to Func
or FunctionEater
).
Upvotes: 1