Search code examples
c++c++11std-functionstdbindmember-initialization

Using std::function in member initialization list


I have a typedef:

typedef S32(iMyDataClass1::*getDataFunction_t)(void);

and a type:

struct functionMap_t {
    std::vector<getDataFunction_t> pDataFunctionTable;
    struct dataRequestor_t dataRequestor;
};

I then have a member variable:

functionMap_t FnMap1;

Which I then set up in an member initializer list:

myClass::myClass() : FnMap1({ 
 {
     &iMyDataClass1::getData1,
     &iMyDataClass1::getData2,
     &iMyDataClass1::getData3
   },
   dataRequestor1
 })

Which I then use in the constructor:

addNewFnMap(FnMap1);

This all works fine. Unfortunately, it's not extendable for function pointers to different classes, as getDataFunction_t is bound to pointers in iMyDataClass1

I tried using templates, but ran into issues that I could not get around. Now I'm trying to use std::function, which means I change the original typedef into (I think):

typedef std::function<S32(void)> getDataFunction_t;

What is the correct way to set up my initializer list in this situation? Do I use std::bind here?

Update: Here is my attempt at a new initializer list. I have no idea if this is correct, but this is what I had right before posting this question:

{ 
  {
    (std::bind(&iMyDataClass1::getData1, functionToFetchCorrectObject())),
    (std::bind(&iMyDataClass1::getData2, functionToFetchCorrectObject())),
    (std::bind(&iMyDataClass1::getData3, functionToFetchCorrectObject()))
  },
  PGN65370
}

Solution

  • You could use lambda expressions. However, if you want to keep the signature as std::function<S32(void)>, you'll need to capture your object.

    myClass::myClass() : FnMap1({
      {
         [this](){ return getData1(); },
         [this](){ return getData2(); },
         [this](){ return getData3(); },
      },
      dataRequestor1
    })
    

    If you don't want to do this, you could change the signature to pass the this pointer as a parameter to your callbacks. But as Barry points out in the comments, this would not allow you to put callbacks to different classes into the same vector. You could reinterpret_cast the pointer inside the lambda but besides from being ugly and dangerous, how would the caller know what pointer to pass in?