mercredi 6 février 2019

pass class member function as argument from another member function of the same class

I have provided a simpler version of the problem, that I am dealing with.

I have class Entity, which has a map of a user object. For simplicity, I have added only one element(name). I have implemented getter and setter around the userMap object.

The wrapper function is required for me, to handle a critical situation because of a multi-threaded case. (not shown here). I have somehow implemented a working example by going through a few SO threads.

But as you can see, I have to write (id,arg) tuple argument in three places while using wrapper function inside procedure function. Is there a way of implementing the same functionality by having some kind of placeholder for the function arguments so that calling the wrapper looks clean, i.e. wrapper(1,static_cast<void*>(&name),function_ptr).

#include <iostream>
#include <functional>
#include <map>
using namespace std;
class Entity {
    public:
        struct user {
            int id;
            string name;
        };
        map<int,user> userMap;

        void getUserName(int id,void * arg);
        void setUserName(int id,void * arg);
        void procedure();
        void wrapper(int id,void*,std::function<void(int,void*)>);
};

void Entity::getUserName(int id,void *arg) {
    auto iter = userMap.find(id);

    if(iter != userMap.end()) {
        *static_cast<string*>(arg) = iter->second.name; 
    }
}

void Entity::setUserName(int id,void *arg) {
    auto iter = userMap.find(id);
    if(iter != userMap.end()) {
        iter->second.name = *static_cast<string*>(arg);
    }
}

void Entity::wrapper(int id,void *arg,std::function<void(int,void*)> func) {
    cout <<"\nSome Other critical task based on id"<< endl;

    // then call the callback
    func(id,arg);
}

void Entity::procedure() {
    cout <<"Procedure starts"<<endl;

    user u = {};
    u.id = 1;
    u.name = "abc";
    this->userMap[1] = u;

    string name;
    wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
        getUserName(id,arg);
    });
    cout <<"name :"<< name << endl;

    cout <<"\nSome processing..."<<endl;

    name = "def";
    wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
        setUserName(id,arg);
    });

    cout <<"\nSome more processing..."<<endl;

    wrapper(1,static_cast<void*>(&name),[this](int id,void*arg){
        getUserName(id,arg);
    });

    cout <<"name :"<< name << endl;

    cout <<"Procedure ends"<<endl;
}

int main() {
    Entity E;
    E.procedure();
}

Output:

Some Other critical task based on id
name :abc

Some processing...

Some Other critical task based on id

Some more processing...

Some Other critical task based on id
name :def
Procedure ends

Thanks!

Aucun commentaire:

Enregistrer un commentaire