How to pass a function as parameter - c++

I have two methods that are mostly the same, so I'm thinking of refactoring them.
A simple version is:
void C::GetEmailAlerts(set<AlertPtr>& alertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isEmail())
alertSet.insert(p);
}
...
}
void C::GetMobileAlerts(set<AlertPtr>& alertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isMobile())
alertSet.insert(p);
}
...
}
Is it possible to make it like:
void C::GetAlerts(set<AlertPtr>& alertSet, ??? func) // How to pass a function as parameter?
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->func())
alertSet.insert(p);
}
...
}
so that I just call:
C c;
c.GetAlerts(emailSet, isEmail);
c.GetAlerts(mobileSet, isMobile);
------------------------ EDIT -----------------------
Maybe a generic example is easier to demonstrate what I would like to have:
#include <iostream>
using namespace std;
struct A
{
int foo() { cout<<"in foo()"<<endl; }
int bar() { cout<<"in bar()"<<endl; }
};
A *instance = new A();
struct C
{
public:
void test1()
{
instance->foo();
}
void test2()
{
instance->bar();
}
// void test(???) // How to pass member function as a pointer?
// {
// instance->f();
// }
};
int main()
{
C c;
c.test1();
c.test2();
// c.test(&A::foo);
// c.test(&A::bar);
return 0;
}
In this second example, I'd like to use c.test(&A::foo); to replace c.test1(), and maybe c.test2, c.test3, ...
Is there a clean way to do this?

Well, depends. If you are using C++11, you can use the auto type and then execute the parameter. Otherwise, you'd need to know if the function is an int, void, char, etc. and then execute the given parameter.

If isEmail like this: bool AlertPtr::isEmail(), you should use the below code:
void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertPtr::*func)())
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->func)
alertSet.insert(p);
}
...
}

Why not cascading your if (pAlert->isMobile()) and if (pAlert->isEmail()) in the same function?
Using function pointer to deal with this problem seems way overengineering.
void C::GetAlerts(set<AlertPtr>& emailAlertSet, set<AlertPtr>& mobileAlertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isEmail()) {
emailAlertSet.insert(p);
else if (pAlert->isMobile()) {
mobileAlertSet.insert(p);
}
}
...
}

Is very simple just use namespaces define each of them in a namespace and can easily access them with the scoop operator

For who might interested, I finally figured out how to do it:
void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertClass::func)())
{
...
if ((pAlert->*func)())
...
}
This is how we call this function:
C c;
c.GetAlerts(emailSet, &AlertClass::isEmail);
c.GetAlerts(mobileSet, &AlertClass::isMobile);
Full solution for the second example:
#include <functional>
#include <iostream>
using namespace std;
struct A
{
int foo() { cout<<"in foo()"<<endl; }
int bar() { cout<<"in bar()"<<endl; }
};
A *instance = new A();
struct C
{
public:
void testFoo()
{
instance->foo();
}
void testBar()
{
instance->bar();
}
void test(int (A::*p)())
{
(instance->*p)();
}
};
int main()
{
C c;
c.testFoo();
c.testBar();
c.test(&A::foo);
c.test(&A::bar);
return 0;
}

Related

losing data when using dynamic_cast to derive object

when I push fifoGroundEvtEntry data inside list_fifoGroundEvt from another thread using sender::GetInstance()->getDataCollector()->pushGroundEventFifo(entry); and when I debug puting one breakpoint inside pushGroundEventFifo function I can see the correct value of grdEvt.x and grdEvt.y inside list_fifoGroundEvt.
then when I call test method inside transmit methode and I pute breakpoint inside test. I see wrong values inside list_fifoGroundEvt-> grdEvt.y = 0x00F12751 for entry.y = 2 !
PS: transmit() is a thread and I start it using sender::GetInstance()->start() (I didn't put all functions I put only those who have a link with the problem )
the thread is starting after pushing entries inside list_fifoGroundEvt
#include "stdafx.h"
#include <iostream>
#include <list>
struct fifoEvtEntry {
virtual ~fifoEvtEntry() {}
int x;
};
struct fifoGroundEvtEntry : fifoEvtEntry
{
int y;
};
class collector {
public:
void pushGroundEventFifo(fifoEvtEntry& entry) {
if (fifoGroundEvtEntry* grdEvt = dynamic_cast<fifoGroundEvtEntry*>(&entry))
{
list_fifoGroundEvt.push_back(grdEvt);
}
}
void test() {
if (fifoGroundEvtEntry* grdEvt = dynamic_cast<fifoGroundEvtEntry*>(list_fifoGroundEvt.front()))
{
std::cout << grdEvt ->y << std::endl;
}
list_fifoGroundEvt.pop_front();
}
private:
std::list<fifoEvtEntry*> list_fifoGroundEvt;
};
class sender {
public:
sender(collector* data):_data(data) {};
~sender() {};
static void setInstance(collector* data) {
_instance = new sender(data);
}
static sender* GetInstance() {
return _instance;
}
void transmit() {
// this is a thread function
// ..
_data->test();
}
collector* getDataCollector(){
return _data;
}
static sender* _instance;
private:
collector* _data;
};
int main(){
return 0;
}

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();
}

How can I call my set my callback function from an object?

Here is some code:
typedef void (*ACallBack)(int i);
class SomeClass
{
private:
ACallBack aCallBack;
public:
void SetCallBack(ACallBack aCallBack);
};
void SomeClass::SetCallBack(ACallBack aCallBack)
{
this->aCallBack = aCallBack;
}
class SomeOtherClass
{
private:
SomeClass someClass;
public:
void InitializeSomeClass();
private:
void callBackMethod(int i);
};
void SomeOtherClass::InitializeSomeClass()
{
this->changeVariable = 10;
this->someClass.SetCallBack(this->callBackMethod); // DOESN'T WORK
this->someClass.UseCallBack();
}
void SomeOtherClass::callBackMethod(int i)
{
}
void globalCallBack(int i)
{
int myInt = i;
}
int main()
{
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
}
Basically if I try to set my callback function in SomeOtherClass it doesn't work but when I set it globally in main it does. What am I missing here?
Just use std::function and std::bind():
typedef std::function<void(int i)> ACallBack;
// old code pretty much the same
int main()
{
using namespace std::placeholders;
SomeClass sC;
sC.SetCallBack(globalCallBack); //WORKS!!
SomeOtherClass oC;
sC.SetCallBack(std::bind(&SomeOtherClass::callBackMethod,oC,_1)); //WORKS AS WELL!!
}
In this case you do not really need to pass void *userData but may add it as well if you need old code to compile.
You have to make the method static:
static void callBackMethod(int i, void* userData);
if you need a pointer to a method that is not static, ie an instance method, it becomes more complex.
typedef void ( myclass::*FUNC ) (int i, void* userData);
and if you want to use it, it becomes a hastlle :
myclass obj; // instantiate myclass
FUNC f = &myclass::myfunc; // assign address
( obj.*f ) ( 123, NULL ); // and call it

how to ( pascal : procedure of object ) in c++

I want to pass a class function as a parameter of C function
in Pascal. It is achieved with the keyword (procedure of object) so the compiler will take care of 'this' parameter.
But it seems complicated in c++.
#include <stdio.h>
typedef void (*func)(void);
class Class{
public:
void sub(void)
{
printf("Foo");
}
};
void test(func f)
{
f();
}
int main()
{
Class c;
test(c.sub);
}
You'll need the function to take a generic function type, either making it a template:
template <typename F>
void test(F f) {
f();
}
or using type erasure:
#include <functional>
void test(std::function<void()> f) {
f();
}
Then use either std::bind or a lambda to bind the member function to the object:
test(std::bind(&Class::sub, &c));
test([&]{c.sub();});
I have been searching for similar issue. There is an answer from someone zayats80888 (thank you).
#include <functional>
using TEventHandler = std::function<void(int)>;
class Button
{
TEventHandler onClick;
public:
Button(){ onClick = NULL;};
void Run() {
if (onClick) onClick(42);
};
};
class Page
{
Button Bnt1;
void ClickHandler(int Arg){/*do smth by Btn1->onClick*/};
Page() {
Btn1 = new Button();
Btn1->onClick = [this](int arg) { goToCountersPage(arg); };
}
}
Page Page1;
void main() {
Page1 = new Page();
//
}

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.