I have a template defined class that handles processing of all the different methods. these methods vary or can be grouped based on type of execution im doing. so I am going to inherit the super class processing attributes but define all the different methods that needs to be processed.
I have function pointer mismatch error. could anyone suggest a solution for this issue
template <class T_ENUM>
class Injection
{
public:
Injection();
~Injection();
virtual void addAllCalls( void );
bool addCall( T_ENUM );
protected:
void* data; // drive of device under test
struct call_info {
T_ENUM call_ref;
string time_stamp;
};
// class specific function pointer defenition
// call_status_s is defined struct
typedef void (Injection::*funcType)(call_status_s*);
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
// here i process the function pointer based on the T_ENUM
bool processCall ( T_ENUM );
virtual void initCallMap( void );
// initialise the functions taken from child class and store here
};
class Type_Injection : public Injection<enum_defined_for_Type> {
public:
void addAllCalls( void );
private:
void initCallMap ( void );
// would initialise func_call_map with the functions pointer of TypeFunction1
// this is the function im going to save as pointers in the list defined in super class
void TypeFunction1 ( call_status_s* );
};
compile error:
error: cannot convert ‘void (Type_Injection::*)(call_status_s*)’ to
‘void (Injection<enum_defined_for_Type>::*)(call_status_s*)’ in
assignment
Again sorry could not add the complete code.
This isn't typesafe, because you have a (hidden) covariant parameter.
The actual function Type_Injection::TypeFunction1 requires a this argument of type Type_Injection. But the call site is only providing an Injection<enum_defined_for_type> and not every instance of the latter actually is one of the former.
It may be that the actual parameter always is of the more derived type, in which case you can use a cast to override the compiler type checking. But I would just use std::function<void (call_status_s*)> instead, and use std::bind when adding the callbacks to the map to specify the target object (assuming that the target object is always the class instance holding the map, and does not vary at call time).
typedef std::function<void (call_status_s*)> funcType;
// map contains all calls initialized and ready to be processed
std::map<T_ENUM, funcType> func_call_map;
void Type_Injection::initCallMap ( void ) override
{
using std::placeholders::_1;
func_call_map[T_ENUM_FUNCTION1] = std::bind(&Type_Injection::TypeFunction1, this, _1);
}
In your particular case, another option is just to make your processCall function that takes in the T_ENUM selector virtual (shouldn't it also accept the call_status_s* function argument to pass to the function being called?). In the derived class, you can use a switch statement to map T_ENUM values to functions in the derived class. This is very efficient, perfectly typesafe, and can delegate to the base class when the value doesn't match/isn't known, to allow different behaviors to be implemented in different levels of the class hierarchy. Unlike a map this only allows lookup, so if iteration is a requirement the map of std::function would be a better option.
Another option is the "Curiously Recurring Template Pattern", which allows the derived class to inform the base class of the real type of the object, so that the map can contain void (DerivedType::*)(call_status_s*) function pointers. But this removes the ability to have behaviors provided at multiple levels of the call tree.
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);
What I'm doing
I'm working on an event system. Basically there are "slots" which any member can chime into. All they need is an event name which it will be listening to, and a function. Since all the slots are stored I had to store them as a variable in a class.
The Problem
The function becomes unavailable when it's placed into the SlotBase class. I am wondering if there is a way to retain the function in the Slot class while storing in in the SlotBase class.
The Code
class SlotBase { };
// TC - Template Class
// TA - Template Arguments (types)
template <class TC, typename ...TA>
class Slot : public SlotBase {
public:
Slot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func);
}
template <int ...Is>
void SetSlot(TC* funcClass, void(TC::*func)(TA...), int_sequence<Is...>) {
function = std::bind(func, funcClass, placeholder_temp<Is>{}...);
}
void SetSlot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func, make_int_sequence<sizeof...(TA)>{});
}
std::function<void(TA...)> returnFunction(){
return function;
}
private:
std::function<void(TA...)> function;
};
//...
class RandomClass {
public:
void randomFunction(int a, float b, int c){ //do stuff };
}
//...
RandomClass randC;
SlotBase baseS;
Slot newSlot(&randC, &RandomClass::randomFunction);
baseS = newSlot;
//...
//Later on down the line when an event was found matching slot call slot function
baseS.returnFunction()(//Correct arguments go here - leaving this out (a lot more code));
I didn't include the code for the integer sequences in the 'std::bind' as it isn't related to the problem.
What I have tried
I know that if I use a Slot cast on the baseS variable that would give me the result but I am unable to do so because I don't know the templates that Slot will have.
I have seen many similar posts stating to make baseS a pointer (such as here) but I still don't understand how you would grab the function.
I think you need to start to accept that at some point if you want to use polymorph objects, you will need to create a virtual function in SlotBase. If you want to cast back to your type at creation before using the function, the polymorphism makes no sense, because you have carried the original type somewhere along with you to be able to do so, so why upcast anyway in the first time ?
If you really need to upcast, then you need to think about a RUNTIME solution to get back to access the derived functionality. In this case, this would mean you need to create a generic interface to your signals, so try to make a pure virtual method in SlotBase that will pack an undefined number of arguments, and implement that generic caller in your Slot so that it unpacks the arguments in order and calls your slot with the arguments. I don't know if variadic methods can be overriden though, that seems dubious. Otherwise you'll have to use boost::any or something to pack the arguments in a runtime collection.
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 :))
I have a solution with many projects.
I would like to make a class inside common project that receive array and pointer to function.
This class is a member in other projects on that solution. each project class can hold it as member.
On the constructor of the class inside common, How do i pass the pointer of the function ? how do i set a member inside the common class that holds the location of the function i would like to invoke later on ?
My goal is that i can invoke the function using the pointer - while im in the code of the class that is found in the common project..
Thanks
On the constructor of the class inside common, How do i pass the
pointer of the function ? how do i set a member inside the common
class that holds the location of the function i would like to invoke
later on ?
typedef void(*FUNCPTR)(int);
This defines my function pointer type, but it also restricts the function to the signature below (retuens void and takes 1 int param) you need to define this for your function signature.
void myFunction( int someParam )
{
//DoSomething with someParam
}
class Foo
{
private:
FUNCPTR mFunction; //Holds pointer
public:
Foo( FUNCPTR function) : mFunction(function) {} //Initialise instance
void callFunc() {mFunction(1);} //call function
};
int main(unsigned int argc, const char** argv)
{
Foo myFoo(myFunction);
myFoo.callFunc();
}
In C++ you might well be better however thinking about using function objects in which you create an object and define an operator() which takes the correct parameters and return type but would allow you all the flexibility of objects and polymorphism....
See C++ Functors - and their uses for some discussion and detail
I have two classes that don't know anything about themselfs class A, class B.
Class A is called the ENGINE,
Class B is called the GUI.
I want GUI class to have a pointer to a function in class ENGINE, so that when an event occurs on GUIControl, it calls ENGINE member function with two parameters (int,int).
Here's how i would like to have it:
class CGUIManager
{
public:
void SetControlCallback(void(*pFunctionPointer)(int,int) );
private:
void (*m_pControlCallbackFunction)(int,int) ;
};
void CGUIManager::SetControlCallback(void(*pFunctionPointer)(int,int) )
{
if(pFunctionPointer)
m_pControlCallbackFunction = pFunctionPointer;
}
class CEngine
{
private:
void GUIControlsCallback(int iControlID, int iControlMessage);
CGUIManager *pGUI;
};
Now while initializing ENGINE, i want to call:
//Set Controls Callback to CEngine Method
pGUI->SetControlsCallback( GUIControlsCallback );
To register a callback within CGUIManager class, that points to a method in CEngine class.
How can i do that?
Thanks in advance.
I would suggest using an interface (or something like that) if you would like it to be oo instead of function pointers ( which must point to a static member btw )
class IGuiCallback
{
public:
virtual void GUIControlsCallback(int iControlID, int iControlMessage)=0;
};
class CGUIManager
{
public:
void SetControlCallback(IGuiCallback*);
private:
IGuiCallback* m_pCallback;
};
class CEngine:public IGuiCallback
{
public:
void GUIControlsCallback(int iControlID, int iControlMessage);
private:
CGUIManager *pGUI;
};
then in engine:
pGUI->SetCallback(this);
There may be some syntax errors in my code but you should get the picture
Pointers-to-member-functions are not function pointers in C++.
To call your callback later (using provided SetControlsCallback signature), the caller need to have a valid instance of CEngine. You can achieve that by binding the pointer to CEngine to GUIControlsCallback:
CEngine* pEngine; // initialized somewhere
pGUI->SetControlsCallback(std::bind1st(pEngine, GUIControlsCallback));
If you use Boost or C++11, you'd better use their versions of bindings (boost::bind or std::bind respectively).
The easiest approach is to use std::function<void(int, int) as the type of the registered callback: this object can be used to call any function [object] which is callable with two ints. In particular, it could call the member function CEngine::GUIControlsCallback(int, int) which actually has three parameters:
the two obvious parameter to the member function of type int
the implicit pointer to the object (which becomes this)
The way this is done is to construct a function object which provides as first parameter a pointer to the CEngine object and takes two integers:
struct CEngine_bind {
CEngine_bind(CEngine* engine): engine_(engine) {}
void operator()(int i0, int i1) { this->engine_->GUIControlsCallback(i0, i1); }
CEngine* engine_;
};
Alternatively, you can use std:bind() which is a create a suitably bound function:
CEngine engine; // ... wherever this object is coming from)
std::function<void(int, int)> callback(std::bind(&CEngine::GUIControlsCallback, &engine,
std::placeholders::_1, std::placeholders::_2));
... and then set the callback object as the callback. This object simply be called passing two integer parameters which will cause the member function on the referenced object to be called:
callback(10, 20);
would call
engine.GUIControlsCallback(10, 20);
The std::function<void(int, int)> is copyable, i.e. you can easily store it in your CGUIManager class.
If you are able to change the interface of the CGUIManager class, I ssugest you generalise it to use boost::function<void(int, int)> (or std::function if writing in C++11) instead of a function pointer.
If you can't, unfortunately you are a victim of bad design. C-style callbacks that use function pointers usually allow for some kind of void* user data parameter to carry any additional information bound to the callback - in this case the your CEngine pointer could be cast to void* and a free function wrapper could be written to cast the void* back to CEngine. However, if you are able to change the callback interface, using boost/STL function is a superior technique.