VladL
VladL

Reputation: 13033

Passing Function Pointer of an interface function

I have following situation, there are two interfaces:

interface ILLShapeAttribute
{
  virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
};

interface ILLShapeNotification
{
  virtual bool IsUsed(const RECT& rcBounds) = 0;
    virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
}

And 2 functions:

INT LlShapeGetAttributeList(LPCWSTR pwszShapefileName, ILLShapeAttribute* pIAttrInfo);
INT LlShapeEnumShapes(LPCWSTR pwszShapefileName, ILLShapeNotification* pIInfo);

In those both functions I want to call the same function IterateRecords2 which should get the pointer to the function DefineAttribute, e.g. ILLShapeAttribute::DefineAttribute and ILLShapeNotification::DefineAttribute

I defined it this way:

void IterateRecords2(ifstream& file, void (*pDefineAttribute)(const char*, VARIANT*))
{
  pDefineAttribute(NULL, NULL); //will be called with real values
}

Until now the code compiles and everythig is fine. But then I try to call the IterateRecords2 like

IterateRecords2(file, pIAttrInfo->DefineAttribute);

or

IterateRecords2(file, pIInfo->DefineAttribute);

I get the compiler error:

error C3867: 'ILLShapeAttribute::DefineAttribute': function call missing argument list; use '&ILLShapeAttribute::DefineAttribute' to create a pointer to member

Please: I know, that ILLShapeNotification could inherit from ILLShapeAttribute and then pass *ILLShapeAttribute instead of function pointer but I want to understand how it works.

Question: how can I pass the pointer to DefineAttribute to IterateRecords2?

Upvotes: 1

Views: 2476

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

Question: how can I pass the pointer to DefineAttribute to IterateRecords2?

You can't.

A pointer-to-member-function is not compatible with a pointer to function, and even if it was, you'd need an object to call it on, you can't just call a member function without an object.

Some options are:

1) Take a pointer-to-member-function and pass an object.

This would solve your compiler error, but to be able to pass different types of object that are not related by inheritance you would need IterateRecords2 to be a template:

template<typename T>
void IterateRecords2(ifstream& file, T* obj, void (T::*pDefineAttribute)(const char*, VARIANT*))
{
  obj->pDefineAttribute(NULL, NULL);
}

Now you can use it like this:

IterateRecords2(file, pIAttrInfo, &ILLShapeAttribute::DefineAttribute);

or:

IterateRecords2(file, pIInfo, &ILLShapeNotification::DefineAttribute);

2) Bind an object and its member function into a callable type, and pass that:

void IterateRecords2(ifstream& file, std::function<void(const char*, VARIANT*)> DefineAttribute)
{
  DefineAttribute(NULL, NULL);
}

Then call it like:

IterateRecords2(file, std::bind(&ILLShapeAttribute::DefineAttribute, pIAttrInfo));

If you can't use std::function and std::bind you can replace them with boost::function and boost::bind

Upvotes: 2

Related Questions