I am working with a template class which parses data. Each line of data will require calling one of two functions to handle the data. This decision is determined at the time the parser is constructed and depends on variables passed to the constructor. I thought it would be useful to use a function pointer for this so that i could use one if statement in the constructor and assign the proper function to the function pointer which will be used in the body of the program. I am getting an error which I cannot figure out and I am curious if I am using the function pointer correctly in this context.
template<class T1, class T2>
class MyClass{
protected:
void (*pDoSomething)(std::string,std::string,std::string);
void functionOne(std::string,std::string,std::string);
void functionTwo(std::string,std::string,std::string);
public:
MyClass(bool option);
void parseData();
};
templace<class T1, class T2>
MyClass<T1,T2,>::MyClass(bool option){
if (option) pDoSomething = &functionOne;
else pDoSomething = &functionTwo;
}
template<class T1, class T2>
void MyClass<T1,T2>::parseData(){
/* . . . */
while(dataToParse){
*pDoSomething(string1, string2, string3);
}
/* . . . */
}
Change it like so:
template<class T1, class T2>
class MyClass
{
typedef void (MyClass::*ptmf)(std::string, std::string, std::string);
ptmf the_function;
explicit MyClass(bool b)
: the_function(b ? &MyClass::functionOne : &MyClass::functionTwo)
{ }
void parse_data()
{
(this->*the_function)(s1, s2, s3);
}
// ...
};
The error is most likely from the use of the function pointer to point to member functions. There is a considerable difference between functions that are in classes and just normal functions. You are assigning a class function to a normal function pointer. The difference comes in when you consider that all member functions take a hidden this pointer as their first argument.
Either change the functions to be outside of the class (or instead use static functions if the functions do not need any of the class's variables, bases or the this pointer) or change the function pointer to a class member function pointer. A pointer to a MyClass function that takes a string will look like this.
void (MyClass::*fptr)(std::string str);
Because the class function pointer requires a hidden this pointer the call of the function pointer changes also. To call the function pointed to by fptr you can use the ->* or .* c++ operators. So to call it using the this pointer of MyClass you can do this:
std::string aString;
(this->*fptr)(aString);
I'm not entirely sure but it maybe possible to do what you hope to do with virtual functions instead? This can be achieved by having two separate classes and a pointer to an instance of one of the two. Both classes derive from a class that has a pure virtual function that is the same as the function you are assigning here. This is a cleaner solution than using function pointers. I would look into this as you may find it useful if your looking for dynamic behavior using function pointers.
This is a good tutorial on the basics of function pointers:
http://www.learncpp.com/cpp-tutorial/78-function-pointers/
Related
I have a class which shall invoke a function specified by the user on certain occasions. Therefore the class has a method void setExternalPostPaintFunction(void(*function)(QPainter&)); that can be used to "register" a function. This function then will be called on that occasion:
class A {
public:
void setExternalPostPaintFunction(void(*function)(QPainter&));
private:
void (*_externalPostPaint)(QPainter&);
bool _externalPostPaintFunctionAssigned;
};
The function pointer is saved in the member variable _externalPostPaint. The implementation of setExternalPostPaintFunction looks like this:
void A::setExternalPostPaintFunction(void(*function)(QPainter&)) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Now, this works with normal functions. However, I want to be able to also pass pointers to member functions of objects. From what I know I also have to pass and store the pointer to the object in this case. However, I don't know which type the other object will have. So I guess I'm forced to use templates. I already thought of something like this:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
void (T::*_externalPostPaint)(QPainter&); //<- This can't work!
bool _externalPostPaintFunctionAssigned;
};
This way I can pass a function pointer and an object pointer to setExternalPostPaintFunction and would probably be able to call the function on the object inside that function. But I'm not able to store it in the variable _externalPostPaint because the type T is only deduced when the function setExternalPostPaintFunction is called, thus I can't have a member variable that depends on this type, since the type of my member variable has to be known when the object is created and apart from that it cannot change, but it would have to in the case when a new function is assigned which possibly could be a member function of an object of different type.
So what is the proper way to do this, or is there any? I'm not super fit with templates and function pointers, so I might have overlooked something.
Anoter option would certainly be to create a functor class with a virtual member function which can be overwritten in a derived class and then pass + store an object pointer of that type instead of the function pointer. But I somehow would prefer my approach if it is somehow possible.
EDIT: SOLUTION
TartanLlama brought me on the right track by suggesting the use of std::function. Here is how I solved it:
class A {
public:
template <typename T>
void setExternalPostPaintFunction(T* object, void(T::*function)(QPainter&)) {
_externalPostPaint = std::bind(function, object, std::placeholders::_1);
_externalPostPaintFunctionAssigned = true;
}
void setExternalPostPaintFunction(std::function<void(QPainter&)> const& function);
private:
std::function<void(QPainter&)> _externalPostPaint;
bool _externalPostPaintFunctionAssigned;
};
As you see, the pointer to the function/member function is stored in an std::function<void(QPainter&)> object now. The advantage is, that an std::function can basically store any callable target. Then there are two overloads: one that can be used for any std::function object that also accepts e.g. a normal function pointer (because the std::function that is expected then is implicitly constructed from that) and one for member functions that have to be called on an object (more for convenience). The latter is implemented as a template. This uses std::bind to create a std::function object of the call of that member function (the user passed) on the object (the user passed).
The overload that takes an std::function is implemented in the source file like this:
void ImageView::setExternalPostPaintFunction(std::function<void(QPainter&)> const& function) {
_externalPostPaint = function;
_externalPostPaintFunctionAssigned = true;
}
Invoking that stored function in the code of class A is now as simple as that:
//canvas is a QPainter instance
if (_externalPostPaintFunctionAssigned) _externalPostPaint(canvas);
The user who wants to register a member function as callback function just has to do the following:
//_imageView is an instance of "A"
//"MainInterface" is the type of "this"
_imageView->setExternalPostPaintFunction(this, &MainInterface::infoPaintFunction);
Or if it's not a member function but just a normal function:
void someFunction(QPainter& painter) {
//do stuff
}
_imageView->setExternalPostPaintFunction(&someFunction);
Or he can explicitly create a std::function object and pass it:
std::function<void(QPainter&)> function = [&](QPainter& painter){ this->infoPaintFunction(painter); };
_imageView->setExternalPostPaintFunction(function);
Works like a charm.
You could use std::function:
class A {
public:
//PostPaintFun can be anything which acts as a function taking a QPainter&
//Could be a lambda, function pointer, functor, etc.
using PostPaintFun = std::function<void(QPainter&)>;
void setExternalPostPaintFunction(PostPaintFun fun);
private:
//Names beginning with an underscore are reserved, don't use them
//Ending with an underscore is fine
PostPaintFun fun_;
bool externalPostPaintFunctionAssigned_;
};
Now you can use member functions like so:
struct B
{
void exec(QPainter&) const;
};
void foo() {
B b;
a.setExternalPostPaintFunction(
[b] (QPainter& p) {b.exec(p);}
);
}
//or inside B
void B::foo() {
a.setExternalPostPaintFunction(
[this] (QPainter&p) {this->exec(p);}
);
}
I have to say I prefer TartanLlama's answer, but here you have something it could work for you.
This might to need some work, but I'm sure you'll get the idea.
struct IFunctionHolder {}; // Used for pointing to any FunctionHolder
typedef IFunctionHolder* functionHolder_ptr; // Alias for IFunctionHolder* .
template<typename Function> // The template for the actual function holders.
struct FunctionHolder: public IFunctionHolder
{
Function function;
};
class A {
public:
template <typename T>
void setExternalPostPaintFunction(void(T::*function)(QPainter&), T* object);
private:
functionHolder_ptr *function_holder; // This memeber can hold eny instantiation of template<> FunctionHolder.
// Instantiate this member wen calling setExternalPostPaintFunction
bool _externalPostPaintFunctionAssigned;
};
You could have some code like this:
A some_a;
void some_a.setExternalPostPaintFunction(&SomeInstance::some_fnunction); // Here take place the instantiation of FunctionHolder.
some_a.function_holder.function(some_painter);
Comment: I'm posting this question again, since some people requested me to post the full code. Here it is:
I have a function pointer typedef that looks like this:
template<typename USER_DATA>
class RowProcessor
{
typedef void (*RowFunction)(USER_DATA, std::vector<USER_DATA> &);
RowProcessor(RowFunction, int) {};
};
and then I'm using in another class UseRowProcessor:
class UseRowProcessor {
public:
void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
void UseRowProcessor::AddUserData(SomeClass c, std::vector<SomeClass> &v) {
v.push_back(c);
}
void UseRowProcessor::LoadUserData() {
RowProcessor<SomeClass> myRowProcessor(AddUserData, 1); // ERROR!!
}
So the error occurs when calling RowProcessor's constructor.
The full error message says that
no insatnce of constructor "RowProcessor<USER_DATA>::RowProcessor [with USER_DATA=SomeClass]" matches the argument list
argument types are: (void (SomeClass c, std::vector<SomeClass, std::allocator<SomeClass>> &v), std::vector<SomeClass, std::allocator<SomeClass>>)
, which I have no idea what it says except for the fact that the constructor arguments do not match..
Why doesn't my AddUserFunction match the function pointer typedef??
TEST LINK<<<<<<<<
Change the function:
void AddUserData(SomeClass, std::vector<SomeClass> &);
to static void AddUserData(SomeClass, std::vector<SomeClass> &); .
As it is a class member function, the this parameter will be added after compiler, so it is not the type of the function pointer. By changing it to static, no this parameter will be added.
As Matt said you need a static function to get this working
class UseRowProcessor {
public:
static void AddUserData(SomeClass, std::vector<SomeClass> &);
void LoadUserData();
};
Here's the completely fixed sample (there were some more issues after fixing to static).
Member functions are different from ordinary functions and this carries over to their type. There is a set of work-arounds that enable you to pass member function pointers to functions that take ordinary function pointers as their parameters, but if you have control over the code you should take a different path. Instead of accepting a function pointer accept a functor.
template<typename Functor>
int f(Functor func) {
// use func like you would a function, e.g. call it with arguments func(1, 2)
}
Now you can call f with a lambda, function object, member function pointer (after you bound it to this), or function pointer.
If you want to avoid templates, accept a std::function instead, but this should only be done if you have special reasons for it.
I am having difficulty getting my head around how to pass a class member function to a subclass (not derived).
My top level class is like this:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList();
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
class CFnList
{
public:
// Public functions
CFnList();
void addFnPtrToList(int index, int (*fn)(void));
private:
// Fn pointer list
typedef struct
{
int index;
int (*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
So basically here I have an instance of class CTop and one of its members is a pointer to a class CFnList. CFnList pointer is instantiated in the constructor of CTop. Then I want to pass in a pointer to one of CTop's member functions to CFnList by calling the following line:
"_funcList->addFnPtrToList(0, &CTop::func1);"
I get issue (quite rightly) that addFnPtrToList does not take the parameters (int, (CTop::*)()). So the compiler knows this function is a certain member function and not just a generic (maybe static) function.
Is there a way to pass the a pointer to the member function into the sub-class? In my case I want the sub-class to be able to call this function. I am thinking I probably have to make static member functions or something, but the syntax is eluding me on how to do this.
All help / advise appreciated.
Fodder
CTop::func1 is a member function. &CTop::func1 is NOT a function pointer, it is a pointer to member (function). Those can not be mixed either in storing or calling. it is not compatible with int (*fn)(void), as the latter takes no arguments and the former requires an object that is passed as the hidden this.
For these reasons you can't have a simple but uniform facility. You either can go with simple function pointers, or pairs of PTM+object pointer, or use wrappers -- handmade or stock like boost::function fueled by boost::bind. If you have C++11 or TR1 you can use the std:: equivalents of the latter.
A declaration in the form:
int (*fn)(void)
cannot point to a member function. It can only point to a free function. Philispophically, this is because the calling conventions for member functions are different then that for free functions. Consider for example the need for a this pointer in the context of a member function call.
The syntax for declaring a pointer-to-member-function is like this:
int (CTop::*fn)(void)
There is an entire section in the C++ FAQ dedicated to member function pointers. Check it out.
You are passing the member function as if it were a regular function. That fails to include the 'this' reference to the class. In order to pass member functions, you have to be able to re-reference it from the original 'this'. Take a look at the following, instead.
typedef void (CTop::*OBJFNC)(args);
_funcList = new CFnList();
_funcList->addFnPtrToList(0, this, &CTop::func1);
void addFnPtrToList(int index, CTop* pobj, OBJFNC pfnc)
{ ... Store both ...
}
Now elsewhere you can execute it with the following.
(pobj->*pfnc)(args);
Here is the final solution, it uses a mixture of passing the instance of the object CTop and usage of template class for CFnList:
My top level class is like this (more or less the same except for the declaration of _funcList to includes the class type and to pass in the "this" to the constructor:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList<CTop>* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList(this);
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
template<class T>
class CFnList
{
public:
// Public functions
CFnList(T *parent);
void addFnPtrToList(int index, int (T::*fn)(void));
private:
// Pointer to the parent (or owner is perhaps more correct)
T* _parent;
// Fn pointer list
typedef struct
{
int index;
int (T::*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
// Constructor
template <class T>
CFnList<T>::CFnList(T *parent) :
_parent(parent),
_fn_list(0)
{
}
// addFnPtrToList:
template <class T>
void CFnList<T>::addFnPtrToList(int index, int (T::*fn)(void))
{
_fn_list.append((fn_list_t){index, fn});
}
So the major changes are:
1. Pass the CTop type in by using changing CFnList into a template.
2. Pass in the instance of the object CTop (so that the pointer to the function can be called) by passing "this" into the constructor and then template class stores it as a pointer to the given template type.... vio-la!...easy :o
Thanks to all who contributed :))
Basically, I have a templated class that runs some algorithm, and that algorithm needs a similarity(T t1, T t2) function that returns a double defining how similar two objects of type T are. This similarity function varies greatly depending on what T is defined as, so the caller of this class needs to define the similarity function. I assume a function pointer is in order, but how do I save a function from a function pointer as a member function for use in the algorithm?
That is, I want to pass in similarity(T t1, T t2) in the class' constructor and be able to call that as a member function throughout the class. How do I do that? Thanks
You can't add member functions to a class at runtime.
You could write a member function that calls the supplied function via the function pointer:
class MyClass {
typedef double (*similarity_fn_type)(T t1, T t2);
similarity_fn_type similarity_fn;
public:
MyClass(similarity_fn_type ptr) : similarity_fn(ptr) {}
double similarity(T t1, T t2) {
return similarity_fn(t1, t2);
}
};
Alternatively, you could make the similarity_fn member public. The syntax for calling it would make it look like a member function, but you might not consider it to be great encapsulation.
There are cleaner, object-oriented ways to do that. One of them is to pass an object with that function, similar to how Java allows reimplementing comparisons with the Comparator class. This implies the creation of a base class (with that function as purely virtual) and a subclass for each implementation of similarity().
In your case, you may find more useful the solution C++11 takes for implementing functions for comparing and hashing. It involves creating special function objects. See std::less and std::hash for examples.
I do something similar to abstract away the process of iterating through a collection. I use a predicate to specify the actual search criteria:
void MyClass::Copy(Class &destination, const Class &source, const std::function<bool (const Effect&)> &predicate)
{
for (size_t i = 0; i < Effect::Max; ++i)
{
const Effect *const pEffect = source.GetEffect(i);
if (predicate(*pEffect))
{
// Do something
}
}
}
void MyClass::CopyInner(Class &destination, const Class &source)
{
this->Copy(destination, source, [](const Effect &effect)
{
return effect.IsInner();
});
}
Note: This uses some C++11 features.
Define a const function pointer member of the appropriate type:
typedef double(*Similarity)(T, T);
const Similarity similarity;
Let the constructor accept a function of that type:
Class(Similarity f) : similarity(f) {}
Then calling the function has the same syntax as calling an ordinary member function:
frobnicate(similarity(foo, bar));
And if the member is public, it cannot be changed out from under you because it’s const.
I have 2 classes
class B {
public:
int func(int i);
};
class A {
public:
typedef int (B::*fPtr)(int);
void run();
B* mB;
};
void A::run() {
// create a pointer
fPtr p = &(B::func);
// invoke the function
mB->*p(2); <------- Compilation Error
}
What i need is to create a pointer to func() in A's run function. I get a compilation error saying that mB is not corresponding to a function with 1 argument.
please help
You need to put parentheses around the function expression:
(mB->*p)(2);
But as others have pointed out, there's almost certainly a better way to do what you're trying to do.
Instance methods on a class always have a hidden first parameter for the this pointer, thus it is incompatible with your function pointer typedef. There is no way directly to obtain a pointer to a member function. The typical workaround is to use a "thunk" where you pass a static function that accepts a generic "catch all" parameter (such as void *) which can be statically cast to a pointer of your choosing on which you can invoke the member function. Example:
class B
{
public:
static void MyThunk(void * obj)
{
static_cast<B *>(obj)->MyRealFunc();
}
void MyRealFunc()
{
// do something here
}
// . . .
};
You can get a pointer to the static function easily as it has no 'hidden this', just reference it using B::MyThunk. If your function requires additional parameters, you can use something like a functor to capture the necesssary parameters and state.
You should definitely read this C++ FAQ Lite page which tells you much more about all this: Pointers to member functions
why can you not call mB->func(2);?
If you need different functions for B perhaps look into virtual functions and class inheritance