How to switch with pointer to member functions? - c++

Well, all I want to do is a "switch" with a function pointer, but with methods pointers. The switch is that if I call the method Run(), it will either redirect to A::RunOn() or A::RunOff() according to Run ptr is pointing to these member functions.
I know it can be done. I did it in plain c but I have searched and googled to do the same thing in c++ but no luck.
class A
{
typedef (void)(A::*RunPtr)(int);
RunPtr RunMethod;
public:
RunMethod Run;
A()
{
Run = RunOff;
}
void SetOn(bool value)
{
if (value)
Run = RunOn;
else
Run = RunOff;
}
void RunOn(int)
{
// RunOn stuff here
}
void RunOff(int)
{
// RunOff stuff here
}
};
So I can call Run() and there will be a switch between the function calls, which I think is more efficient than just doing:
if (on)
RunOn();
else
RunOff();
Don't know how to do it!

Your member function pointer typedef is wrong (Despite the other issues in the shown code). You need
typedef void(A::*RunPtr)(int);
Or you can provide the alias for the member function pointer of class A with the help of using keyword as follows:
using RunPtr = void(A::*)(int);
RunPtr RunMethod;
Now in the SetOn you can do member pointer assignment as follows
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
Now, in order to call the stored member function pointer, you may/ can provide a Run member function as follows:
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
The call to member function is a bit tricky.
However, this can be done using more generic std::invoke from <functional> header (Since c++17).
Here is the complete example:
#include <iostream>
#include <functional> // std::invoke
class A
{
using RunPtr = void(A::*)(int);
// or with typedef
// typedef void(A::*RunPtr)(int);
RunPtr RunMethod;
public:
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
void RunOn(int arg) { std::cout << "RunOn: " << arg << "\n"; }
void RunOff(int arg) { std::cout << "RunOff: " << arg << "\n"; }
};
int main()
{
A obj;
obj.SetOn(true);
obj.Run(1); // prints: RunOn: 1
obj.SetOn(false);
obj.Run(0); // prints: RunOff: 0
}
(See a Demo)

Your code works fine once you fix the syntax mistakes in it, namely:
Class needs to be class.
in RunMethod Run;, RunMethod is not a type, it is a member variable. You meant to use RunPtr Run; instead (and get rid of RunMethod), but that won't work so well for you (see further below for why).
in Run = RunOn; and Run = RunOff;, you need to fully qualify the method name, and prefix it with the & operator, eg Run = &A::RunOn;.
Try the following:
class A {
public:
typedef void (A::*RunPtr)(int);
RunPtr Run;
A()
{
Run = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
Run = &A::RunOn;
else
Run = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
}
void RunOff(int param)
{
//RunOff stuff here
}
};
Note, however, that even though you can use Run as a public method pointer like this, the caller will still need to use operator.* or operator->* to actually call it, and that would not look so nice, eg:
A a;
(a.*a.Run)(...);
Online Demo
If you want to be able to call Run() like a.Run(...) then you have to make Run() be a standard method, and have it use a method pointer internally, eg:
class A {
typedef void (A::*RunPtr)(int);
RunPtr RunMethod;
public:
A()
{
RunMethod = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
RunMethod = &A::RunOn;
else
RunMethod = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
cout << "RunOn: " << param << endl;
}
void RunOff(int param)
{
//RunOff stuff here
cout << "RunOff: " << param << endl;
}
void Run(int param)
{
(this->*RunMethod)(param);
}
};
A a;
a.Run(...);
Online Demo

Related

How to Call function pointer from other class

let's say I have simple class with some simple function pointer, like that:
class ClassWithFuncPointer
{
public:
inline void firstFunction() { /* do something */ };
inline void secondFunction() { /* do something */ };
// MY FUNCTION POINTER
void (ClassWithFuncPointer::*funcPointer) ();
// AND I CAN DEFINE IT BY DEFAULT IN CONSTRUCTOR LIKE THAT:
ClassWithFuncPointer()
{
funcPointer = &ClassWithFuncPointer::firstFunction;
}
// AND NOW I CAN USE MY FUNCTION POINTER INSIDE OF ClassWithFuncPointer, LIKE THAT:
void useFunctionPointer()
{
(this->*funcPointer )();
}
}
So here (this->*funcPointer )(); do the job.
But I can't figure it out how to use my funcPointer from other class, I mean something like that:
class otherClass
{
otherClass(){};
ClassWithFuncPointer instanceOfClassWithFuncPointer;
}
And now how can I use funcPointer inside otherClass on member of instanceOfClassWithFuncPointer. Is it possible at all?
I tried many variants:
(this->*instanceOfClassWithFuncPointer.funcPointer)();
or
(instanceOfClassWithFuncPointer.*funcPointer)();
or
( (&instanceOfClassWithFuncPointer)->*funcPointer )();
or just
instanceOfClassWithFuncPointer.funcPointer();
but always get error. I can't figure it out.
What about (C++11 or newer only) as follows?
auto fp = instanceOfClassWithFuncPointer.funcPointer;
(instanceOfClassWithFuncPointer.*fp)();
Or also (C++98 compatible, maybe using shorter variable names) ?
(instanceOfClassWithFuncPointer.*instanceOfClassWithFuncPointer.funcPointer)();
The following is a full working example
#include <iostream>
struct ClassWithFuncPointer
{
public:
inline void firstFunction ()
{ std::cout << "cwfp::firstFunction()" << std::endl; }
inline void secondFunction ()
{ std::cout << "cwfp::secondFunction()" << std::endl; }
void (ClassWithFuncPointer::*funcPointer) ();
ClassWithFuncPointer()
{ funcPointer = &ClassWithFuncPointer::firstFunction; }
void useFunctionPointer()
{ (this->*funcPointer )(); }
};
class otherClass
{
public:
otherClass ()
{ }
ClassWithFuncPointer instanceOfClassWithFuncPointer;
void foo ()
{
auto fp = instanceOfClassWithFuncPointer.funcPointer;
(instanceOfClassWithFuncPointer.*fp)();
}
};
int main ()
{
otherClass oc;
oc.foo();
}

Pointer to function-member

I have a FreeRTOS function xTaskCreate. Simplified declaration looks like
typedef void (*TaskFunction_t)( void* );
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void*params );
And there are two classes:
class Super {
virtual void task(void*params) = 0;
};
class Derived1 : public Super {
virtual void task(void*params){ while(1){ blinkLed(1); delay_ms(333); } }
};
class Derived2 : public Super { ... ;}
In function init() I select one of derived classes and create its instance. Then want to create task
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate( obj->task ); // WRONG.
}
Upd. Add missed void*params in Simplified declaration of xTaskCreate.
TaskFunction_t is just a pointer to a function - so it can't take a pointer to a member function. Only a pointer to normal function. Or a static member function. Or a lambda with no capture. It's that last one that we'll take advantage of.
One of the arguments you removed from your simplified declaration is the context:
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void *pvParameters, // <== this one!
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);
You provide the Super* in the parameters and provide a lambda that knows what to do with it. Altogether:
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate([](void* o){ static_cast<Super*>(o)->task(); },
..., // other args here
obj,
... // more args
);
}
Note that task() should take no arguments. The void*is the context that we're converting to a Super*.
After several experiements of my own with answers here I prefered this simpler method giving Object oriented function calls to RTOS tasks.
//These are not full declaration of class IModule which is fully abstarct so //object that are IModule* are always inherited.
protected:
virtual int InitModule() = 0;
virtual bool PreLoop() = 0;
virtual bool DoLoop() = 0;
virtual bool PostLoop() = 0;
virtual bool DoShutdown() = 0;
//Return if this module implementation requires an RTOS task looping.
virtual bool isFreeRTOSTaskRequired() = 0;
private:
TaskHandle_t *moduleLoopTaskHandle;
bool CreateRTOSTask();
static void TaskStart(void* taskStartParameters);
void TaskLoop();
//END OF PARTIAL decleration
bool IModule::CreateRTOSTask()
{
xTaskCreate(IModule::TaskStart, "NAME", 2048, this, tskNO_AFFINITY, moduleLoopTaskHandle);
return true;
}
void IModule::TaskStart(void *taskStartParameters)
{
IModule *moduleObject = (IModule *)taskStartParameters;
moduleObject->TaskLoop();
}
void IModule::TaskLoop()
{
//TODO Buraya ölçüm koyalım ve bir değişkene yazalım
while (true)
{
ESP_LOGD("IModule::TaskLoop", "%s", "I am alive!");
if (!PreLoop())
{
}
if (!DoLoop())
{
}
if (!PostLoop())
{
}
}
vTaskDelete(NULL);
}
UPDATED: See below.
As explained better than I can here, you might get away with this. Hard to tell from your question if it will cover all of your requirements.
typedef void (Super::*TaskFunction_t)( void* );
Further Reading
UPDATE:
I fleshed out your example, and the results and code are below:
XXXXX:~/scratch/member_function_pointer$ bin/provemeright
Condition false
virtual void Derived2::task(void*)
XXXXX:~/scratch/member_function_pointer$ bin/provemeright foo
Condition true because of argument foo
virtual void Derived1::task(void*)
code (all one cpp file, bad form, but proves syntax):
#include <iostream>
class Super;
typedef void (Super::*TaskFunction_t)(void*);
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params);
bool condition = false;
class Super {
public: virtual void task(void* params) = 0;
};
class Derived1 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
class Derived2 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
void init(){
Super *obj = condition ? (Super*)new Derived1 : (Super*)new Derived2;
xTaskCreate( &Super::task , obj);
}
int main(int argc, char **argv)
{
if(argc > 1)
{
std::cout << "Condition true because of argument " << argv[1] << std::endl;
condition = true;
} else {
std::cout << "Condition false" << std::endl;
}
init();
return 0;
}
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params)
{
Super *obj = (Super*) params;
(obj->*pxTaskCode)(NULL);
return 0;
}
If you're concerned that the syntax is &Super::task instead of &obj->task, then you're misunderstanding how virtual functions work. (It turns out that the &obj->task syntax forbidden by ISO C++, but gcc says it's permissive, so you shouldn't but could force it to compile, and get exactly the same result)
The information about which virtual version of a function to call 'lives' in the object, not the type system. (Could probably phrase that better, open to suggestions, but I think it gets the general point across) It is impossible to call a member function without an object, so in order to make use of the function pointer, you'll have to have an object to 'call it on'. It is the type of that object which will determine which virtual function gets called. So the code above should achieve whatever you're going for, unless of course, this is a round-about way to determine the type of the object pointed to by obj, in which case, it's an awfully convoluted way of going about it.
Further Reading specifically in "Kerrek SB"s answer.

One function that can use dynamic function swapping

This might sound a little convoluted, but here we go.
So, I have the following code:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->func(100);
}
Firstly, This code is designed to validate a single integer. That part is easy.
Then, what I want it to do is carry out a function depending on if the integer meets the condition or not. In this case, setPetHunger() is being set to either 0 or 100. The issue is, I have setPetHealth(), and setPetEnergy() too.
The function I want it to perform is the thing that I want to change.
For instance. This code will only work for my pets Hunger. It won't work for it's Health, Happiness, or any of it's other variables. and I have a ton of other variables.
I'm wondering if there is any way to achieve something like this:
void Utility::validateRangeAndModify(Pet pet,
int checkint,
int numbertovalidate,
bool greaterorless,
string functiontouse)
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
pet.getAttributes()->FUNCTION_TO_USE(100);
}
I could use something like reflection for this in C#. However, I don't know an alternative function in c++
You can do it by passing the correct member function pointer as parameter to Utility::validateRangeAndModify as below:
void
Utility::validateRangeAndModify(Pet &pet, int checkint, int numbertovalidate,
bool greaterorless, void(Attrib::*memfun)(int)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^
if(greaterorless) {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(0);
} else {
if(numbertovalidate < checkint) (pet.getAttributes()->*memfun)(100);
}
}
And then call it as (if Utility::validateRangeAndModify is not static use obj.validateRangeAndModify):
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetHunger);
Utility::validateRangeAndModify(p, 10, 9, false, &Attrib::setPetThirst);
LIVE DEMO
You should use a function pointer:
void Utility::validateRangeAndModify(Pet pet, int checkint,
int numbertovalidate,
bool greaterorless,
void (*func)(int, attribs &))
{
if (greaterorless) {
if (numbertovalidate < checkint)
pet.getAttributes()->setPetHunger(0);
} else
if (numbertovalidate > checkint)
func(100, pet.getAttribs());
}
You and the client will agree on the prototype of the function that you will pass; in this case, the prototype will be void func(int, attribs &);
The client can write code like this:
void happiness(int level, attribs &a)
{
// some code here
}
Utility::validateRangeAndModify(..., happiness);
Now happiness willl be called by your validateRangeAndModify function.
NOTE: happiness is a free function. If it is a member function, mark it as static: then there won't be the extra this argument.
To keep this simple, I'm providing a really trivial program that uses std::bind, std::function, and std::placeholders to allow calls to a bound method. This keeps the correct this with the method and generally prevents nastiness.
#include <iostream>
#include <functional>
// bait class to catch bound function calls. Replace this with pet for OP's example
class TwoMethods
{
public:
void method1(int val)
{
std::cout << "Method 1 received " << val << std::endl;
}
void method2(int val)
{
std::cout << "Method 2 received " << val << std::endl;
}
};
// utility function that will operate on a bound function
void utilityfunction(std::function<void(int)> func)
{
// calls passed function. Quietly handles bound this parameter and replaces
// placeholder with 42
func(42);
}
int main()
{
TwoMethods obj;
// call utility function with appropriate object and method
// the std::placeholders::_1 lets the compiler know there is another parameter that
// will be supplied later
utilityfunction(std::bind(&TwoMethods::method1, obj, std::placeholders::_1));
utilityfunction(std::bind(&TwoMethods::method2, obj, std::placeholders::_1));
}
In OP's case:
void Utility::validateRangeAndModify(int checkint,
int numbertovalidate,
bool greaterorless,
std::function<void(int)> func)
{
switch (greaterorless)
{
case 0:
{
if (numbertovalidate < checkint)
{
func(0);
}
}
break;
case 1:
{
if (numbertovalidate > checkint)
{
func(100);
}
break;
}
}
}
And called something like:
validateRangeAndModify(42, 666, false,
std::bind(&Attributes::setPetHunger,
pet.getAttributes(),
std::placeholders::_1))

Macro to return the 'this' pointer, or NULL when it's not available

Is it possible to access the this pointer in non-static context and use something else in static context automatically? Do you know any macro or template magic?
#define LOG std::cout << _is_the_this_pointer_available_ ? this : 0
class Foo {
void test() {
LOG;
}
};
void staticTest() {
LOG;
}
Do you know any macro or template magic?
Honestly, I wouldn't do this with a macro. When something can be done without macros, I'd suggest to prefer avoiding them. Here is a possible solution based on overloading, CRTP, and inheritance (no macros):
int get_this() { return 0; }
template<typename T>
struct get_this_helper
{
T* get_this() { return static_cast<T*>(this); }
};
The only overhead is that you have to make your classes derive from the proper specialization of get_this_helper<>, as shown below:
#include <iostream>
#define LOG std::cout << get_this() << std::endl;
class Foo : public get_this_helper<Foo> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// This is the only thing that requires
// being changed wrt your version of Foo
public:
void test() {
LOG;
}
};
void staticTest() {
LOG;
}
Here is a simple test program:
int main()
{
Foo f;
f.test();
staticTest();
}
And a live example.
I am using the following technique to write this pointer to a log:
#define GET_THIS() __if_exists(this) { this; } __if_not_exists(this) { nullptr; }
However it is Microsoft specific.
#define LOG std::cout << isThisAvailable()
bool isThisAvailable() { return false; }
struct X
{
bool isThisAvailable() { return true; }
void test() { LOG; }
};
void staticTest()
{
LOG;
}
Calling isThisAvailable inside the class will return true. Calling outside the class context will call the free function and return false.

What is the syntax for storing a specific class's member functions in a vector?

I did quite a bit of searching, but the combination of * () and class scope has greatly hindered me in understanding of the syntax, with each edit throwing a new error, any help guys?
What I'm trying to do:
Declare a std::vector of pointers to member functions found in MyClass.h
Assign the actual member functions to the std::vector in MyClass.cpp's constructor
The member functions are not static
Thanks!
I'm curious where you're going to use them from. You see in order to call a C++ class member function you need to have an instance pointer with which to call it (each member function needs a this in order to access the class state). So normally you'd wrap the member function pointer together with the instance pointer with std::bind and then maybe store the result in std::function. To put them in vector they're all going to need the same signature.
Is this the kind of thing you were looking for:
class P
{
typedef std::function<void (void)> func_t;
std::vector<func_t> functions;
public:
P()
{
functions.push_back(std::bind(&P::foo1, this));
functions.push_back(std::bind(&P::foo2, this));
functions.push_back(std::bind(&P::foo3, this));
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call()
{
for(auto it = functions.begin(); it != functions.end(); ++it)
{
(*it)();
}
}
};
int main()
{
P p;
p.call();
}
After further clarification from the OP I'll propose this:
class P
{
typedef std::function<void (void)> func_t;
std::map<const char*, func_t> functions;
public:
P()
{
functions["foo1"] = std::bind(&P::foo1, this);
functions["foo2"] = std::bind(&P::foo2, this);
functions["foo3"] = std::bind(&P::foo3, this);
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call_by_name(const char* func_name)
{
functions[func_name]();
}
};
int main()
{
P p;
p.call_by_name("foo1");
p.call_by_name("foo2");
p.call_by_name("foo3");
}
You can use member function pointers like this (the C++11 is unrelated to that part):
struct S {
int foo(){std::cout<<"foo"; return 0;}
int bar(){std::cout<<"bar"; return 0;}
};
int main() {
std::vector<int(S::*)()> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
(s.*func)();
}
}
However, if you use C++11, std::function can make it a bit cleaner:
std::vector<std::function<int(S &)>> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
func(s);
}
If you use C++03, Boost has boost::function, which is similar.