Home > Net >  How to define a lambda function to be able to capture the 'this' pointer of a class?
How to define a lambda function to be able to capture the 'this' pointer of a class?

Time:10-27

I have a time class which tracks the time.

I want my other classes to be able to register a callback function if the day changes.

I have this working snippet:

#define MAX_CB_CHANGE_FUNCTIONS 50
typedef void (*dayChangeFunc)(int prevDay,int nowDay);

class TimeSystem {
    private:
        // array for the function pointers.
        dayChangeFunc dayChangeFunctions[MAX_CB_CHANGE_FUNCTIONS];
        // emit function if the day changes.
        void emitDayChange(int prev, int now);
    public:
        void regDayChange(dayChangeFunc);
};


/*
*   Registering a day change function.
*   Maximum function pointer count is MAX_CB_CHANGE_FUNCTIONS ( see timeSys.h )
*/
void TimeSystem::regDayChange(void (*dayChangeFunc)(int prevDay,int nowDay)){
    if( currDayCbIndex >= MAX_CB_CHANGE_FUNCTIONS ){
        if(isDebugOn){
            debug.print(DEBUG_WARN,"[Time_sys] - Can not register an other day change function.\n");
            return;
        }
    }
    dayChangeFunctions[currDayCbIndex] = dayChangeFunc;
    currDayCbIndex  ;
}

/*
*   Emitting day change to every registered function.
*/
void TimeSystem::emitDayChange(int prev, int now){
    // Preventing change on initialization.
    if( prev == 0 ){ return; }
    for (size_t i = 0; i < MAX_CB_CHANGE_FUNCTIONS; i  ){
        if(dayChangeFunctions[i]){
            dayChangeFunctions[i](prev,now);
        }
    }
}

This works and other calsses can use this like this:

timeSys.regDayChange([](int prevDay,int nowDay){
    Serial.printf("Day changed from prev: %d to now: %d\n",prevDay,nowDay);
});

Now i want to capture the 'this' pointer in the lambda to be able to call some internal function of a class.

timeSys.regDayChange([this](int prevDay,int nowDay){
    callSomeInternalFunction();
});

Error i get:

no suitable conversion function from "lambda [](int prevDay, int nowDay)->void" to "dayChangeFunc"

How could i define my lambda to be able to capture the 'this' pointer?

******** EDIT: SOLVED ********

Here are the modifications:

I had to define my lambda function type like this:

using dayChangeFunc = std::function<void(int, int)>;

Define the function pointer register function like this:

void regDayChange(dayChangeFunc cb);

And rewrite the declaration like this:

/*
*   Registering a day change function.
*   Maximum function pointer count is MAX_CB_CHANGE_FUNCTIONS ( see timeSys.h )
*/
void TimeSystem::regDayChange( dayChangeFunc cb ){
    if( currDayCbIndex >= MAX_CB_CHANGE_FUNCTIONS ){
        if(isDebugOn){
            debug.print(DEBUG_WARN,"[Time_sys] - Can not register an other day change function.\n");
            return;
        }
    }
    dayChangeFunctions[currDayCbIndex] = cb;
    currDayCbIndex  ;
}

And now i can use it in any class like this:

class SampleClass(){
  private:
     int exampleCounter = 0;
  public:
    void init(){
      TimeSystem timeSys;
      timeSys.regDayChange([this](int prevDay,int nowDay){
        Serial.printf("Day changed from prev: %d to now: %d\n",prevDay,nowDay);
        exampleCounter  ;
      });
    }
}

CodePudding user response:

Change the callback type to std::function<void(int, int)>

using dayChangeFunc = std::function<void(int, int)>;

or

typedef std::function<void(int, int)> dayChangeFunc;

and change the function prototype,

void TimeSystem::regDayChange(dayChangeFunc func).

(If you had used your type alias consistently you wouldn't have needed to change the prototype, only the alias itself. Type aliases are most useful if you use them.)

CodePudding user response:

A lambda function that captures anything cannot be converted to a function pointer. You need to pass a pointer manually, or need to have a 'pool' of functions, each storing the current this pointer globally.

  • Related