In my code I would like to call different functions by the same name. So I used pointers, and I did work with static functions, now I would like to do the same with non-static functions and it doesn't work at all.
class Amrorder
: {
public:
....
void (*fkt)(real&, const real);
void fktAcPulse(real &rhoRef, const real y);
void fktAcPulseSol(real &rhoRef, const real y);
...
}
void Amrorder::initData(a)
{
...
switch(method){
case 2://
Amrorder::fkt=&Amrorder::fktAcPulse;
break;
case 222://
Amrorder::fkt=&Amrorder::fktAcPulse1d;
break;
}
...
for(int i=0; i<ng; ++i){
Amrorder::fkt(rhoRef, yRef);
...
}
...
}
The code is quiet big so I hope the part above is enough to understand what I want to do.
Thanks for your time!
It doesn't work because your fkt has type:
void (*)(real&, const real);
and you're trying to assign it to, e.g., &Amrorder::fktAcPulse, which has type:
void (Amrorder::*)(real&, const real);
Notice the difference. The latter is a pointer-to-member function, not just a pointer to function. These have different semantics. A pointer to function can just be called (e.g. fkt(a, b)), but a pointer to member function needs to be called on an object (e.g. (obj.*pm)(a, b)).
For simplicity, since you probably just want "something that I can call with a real& and a const real", you may want to consider the type-erased function object: std::function:
std::function<void(real&, const real)> fkt;
This can be initialized with any callable that matches the arguments, so you can assign it to a free function:
void foo(real&, const real) { ... }
fkt = foo;
A static member function:
struct S { static void bar(real&, const real) { ... } };
fkt = &S::bar;
Or a member function, as long as its bound:
fkt = std::bind(&Amrorder::fktAcPulse, this);
fkt = [this](real& a, const real b){ return this->fktAcPulse(a, b); };
The key is that you need an instance of Amrorder to call fktAcPulse, and using std::function lets you use either std::bind or a lambda to store that instance in with the functor itself.
The type of fkt declares a function pointer to a free-standing function or a static member function. But you want to assign a non-static member function pointer to it. So fkt needs to be of the type of a non-static member function pointer of class Amrorder. That type is spelled
void (Amrorder::*fkt)(real&, const real);
// ^^^^^^^^^^
When invoking a function pointer to a non-static member function, you need to specify on which object you want the member to be called (which normally defaults to this when calling a member function directly with its name).
The syntax for this is quite strange. It requires another pair of parentheses and depends on wether you call it on a pointer or an object itself:
(object.*functionPointer)(arguments);
(pointer->*functionPointer)(arguments);
So if you just want to call the function on the this pointer, you need to write
(this->*fkt)(rhoRef, yRef);
(Note that you don't need to specify the class in your code everywhere. Amrorder:: can be removed in front of every function name inside the definition of a member function of the same class.)
When you call a non-static method of a class, the compiler needs to know which instance of the class you want to execute against. So there is a hidden parameter in the call, which is a pointer to the instance.
So you need to write something like this:
Amrorder::fkt=bind( &Amrorder::fktAcPulse, this );
Related
This question already has answers here:
C++ function pointer and member function pointer
(3 answers)
Closed 2 years ago.
typedef void (*funcPtrType)(); // function pointer type
map<char,funcPtrType>eventGroups;
void addSharedEvent(char groupIndex,void (*receiverFunc)() ){
if(groupIndex==0)
return;
eventGroups[groupIndex]=receiverFunc;
}
It works if adding inline functions but not if using non inlined class member functions like below...
void MainWin::uiValsUpdated()
{
}
void MainWin::test()
{
//invalid
wSync.addSharedEvent(4,&uiValsUpdated);
}
How to make universal pointer for accessing functions in various types of classes?
Alternatively could define class types also but still in universal manner like Qtˇs signals and slots for example.
typedef void (*funcPtrType)(); // function pointer type
Avoid obfuscating pointer types like this.
It works if adding inline functions but not if using non inlined class member
It has nothing to do inline vs non-inline, and everything to do with the fact that a function pointer cannot point to a non-static member function.
How to make universal pointer for accessing functions in various types of classes?
A function pointer can point to functions except non-static member functions as long as the prototype matches. To call such function, no class instance is required. Example:
void free_function() {}
auto fun_ptr = &free_function;
fun_ptr();
A pointer to member function can point to non-static member functions of a particular class with matching prototype. In order to call such pointed function, there must be an instance of the class. Example:
struct foo {
void member_function(){}
};
auto mem_fun_ptr = &foo::member_function;
foo f;
f.*mem_fun_ptr();
A function object can be used as a wrapper, and it can call any type of functions. If you want to call a member function, the needed instance can for example be stored as a member. A lambda is a shorthand for creating such function object. Example:
auto lambda_free = [] {
free_function();
}
auto lambda_member = [f] {
f.member_function();
}
lambda_free();
lambda_member();
Type erasure techniques can be used to hide the type of various function objects, since they can be called in the exactly same manner. Standard comes with a template for such purpose: std::function. Example:
std::function<void()> fun_wrapper;
fun_wrapper = lambda_free;
fun_wrapper = lambda_member;
fun_wrapper = fun_ptr;
//fun_wrapper = mem_fun_ptr; // nope; there is no instance of foo
Pointers to free functions are very different from those that point to member functions. Not only is the syntax different, member function pointers also need a this first argument - the instance of their class they are supposed to operate on. You cannot use the same map to store both, if you intend to deal with raw (member) function pointers.
One solution is some kind of type erasure; you can store std::function objects in your map:
map<char, std::function<void()>>eventGroups;
void addSharedEvent(char groupIndex, const std::function<void()>& callback){ ... }
You can construct the parameter by plain function pointers, and in case of member functions usage of std::bind or a lambda.
I have two claces.
here is the first one
class one{
one(){ }
public:
void change(double a){
//print a
}
void run(){
two tw;
tw->functionpointer=&change;
}
};
and here is the two class
public two{
two();
static void progresschange(double v){
functionpointer(v);
}
public:
void (*functionpointer)(double);
};
as you see in example I have a function in class one, I want to call it from an static function in class two As progresschange is static I can only call change function in class one uisng function pointers. but It does not work and compiles says
error: cannot convert ‘void (one::*)(double)’ to ‘void (*)(double)’ in assignment
it happens in this line
tw->functionpointer=&change;
how can I make it work. it is even possible to pass a function using its function pointer to another class using this method?
thanks
The error message is quite straightforward:
error: cannot convert void (one::*)(double) to void (*)(double) in assignment
void one::change(double) is a member function of the class one, not just a function. Therefore, you can't assign a pointer to this member function (i.e.: void (one::*)(double)) to a pointer to a function with the same signature (i.e.: to a void (*)(double)).
Besides, a non-static member function (like one::change() above) has to be called on an object, so you also need to provide an one object to call that pointed-to non-static member function.
Basically, you can achieve what you want by adding the following data members in two:
void (one::*mem_func_ptr)(double);
one *obj_ptr;
That is, a pointer to the member function (mem_func_ptr) and a pointer to the object to call this member function on (obj_ptr).
To assign to the member function pointer:
mem_func_ptr = &one::change;
Then, to call the member function pointed by mem_func_ptr on the object pointed by obj_ptr with 0.0 as argument:
(obj_ptr->*mem_func_ptr)(0.0);
It can be done analogously by keeping a copy of an object one as data member instead of a ponter. In that case you should use the operator .* instead of ->*.
The problem is that one::change() is a class member so you need to pass a pointer to a class instance as well.
The modern way to do it is to use std::function, std::bind and std::mem_fn:
class two {
....
std::function<void(double)> functionpointer;
}
tw->functionpointer = std::bind(std::mem_fn(&one::change), _1, one_instance);
Alternatively you can use a lambda function:
tw->functionpointer = [&one_instance](double x) { one_instance->change(x); }
sorry for possible duplicates, but I didn't understand the examples and codes snippets I found.
I have a class named "EncoderWrapper" which includes some functions. One of these functions is called "onAfterTouch" and is declared in the "EncoderWrapper.h" file.
void onAfterTouch(byte channel, byte pressure);
The functions will become a callback for another class function of a library I use
inline void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
usb_midi_handleAfterTouch = fptr;
};
Note: I'm totally new to C++, so I want to say sorry if I'm doing some "no-gos" or mixing up some terms.
The question is: How can I pass my class function (member function?) to that "setHandleAfterTouch" function of the library?
This won't work:
void EncoderWrapper::attachMIDIEvents()
{
usbMIDI.setHandleAfterTouch(&EncoderWrapper::onAfterTouch);
}
... my IDE says
no matching function for call usb_midi_class:setHandleAfterTouch(void (EncoderWrapper::*)(byte, byte))
I've also tried
usbMIDI.setHandleAfterTouch((&this->onAfterTouch));
But this won't work ... and I don't get the approach on that.
Every Help is very appreciated ;-)
Function pointer and member function pointer have different types. You can it for yourself:
struct Test {
void fun();
};
int main() {
void(*ptr)() = &Test::fun; // error!
}
Instead, member function pointer need this syntax:
void(Test::*fun)() = &Test::fun; // works!
Why you ask? Because member function need an instance to be called with. And calling that function have a special syntax too:
Test t;
(t.*funptr)();
To accept member function pointer, you'll need to change your code to this:
inline void setHandleAfterTouch(void(EncodeWrapper::*fptr)(uint8_t, uint8_t)) {
usb_midi_handleAfterTouch = fptr;
};
Since it's rather limiting accepting only the functions from one class, I recommend using std::function:
inline void setHandleAfterTouch(std::function<void(uint8_t, uint8_t)> fptr) {
usb_midi_handleAfterTouch = std::move(fptr);
};
This will allow you to send lambda with captures, and call your member function insode it:
// we capture this to use member function inside
// v---
usbMIDI.setHandleAfterTouch([this](uint8_t, channel, uint8_t pressure) {
onAfterTouch(channel, pressure);
});
It seems you can't change, and by looking quickly at the API, it doesn't seem you have access to a state object.
In that case, if you want to use your member function, you need to introduce a global state:
// global variable
EncodeWrapper* encode = nullptr;
// in your function that sets the handle
encode = this; // v--- No capture makes it convertible to a function pointer
usbMIDI.setHandleAfterTouch([](uint8_t, channel, uint8_t pressure) {
encode->onAfterTouch(channel, pressure);
});
Another solution would be to make onAfterTouch function static. If it's static, it's pointer is not a member function pointer, but a normal function pointer.
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);
I don't understand why the following code compile and works:
template<typename Predicate>
void foo(Predicate p) {
}
bool g(int n) {
}
void user(int n) {
foo(g);
}
foo is supposed to get a function object that will run on a data structure but I made the method simpler, because what I don't understand is how can this works? A method isn't an object. The normal way to do it is to create a new class, override operator() and then send an instance of that class.
Well, in this case the Predicate parameter is substituted by a function pointer of type bool (*func) (int). Nothing wrong with that...
The Predicate template argument can be almost any type. So you can use it for function pointers and classes as well as the basic types.
If you use the function argument p as a function, then it can be anything that is callable, like a function pointer, an object whose class have an operator() member function, a pointer to a static member function, a std::bind object, a std::function object or a lambda expression.
It can't be a pointer to a member function though, because to call a pointer to a member function you need an instance to call it on. For this use std::bind.