Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How declare a C++ mem_fn(member_function) in function declaration?

I understand the basic problem in passing the address of a member function outside of its class. I get the feeling that mem_fn() might be the solution but I am having trouble with the specifics.

I have a member function in class p that is currently declared as

typedef void (*valNamedFlagsCallback)(const int, const bool);
bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], valNamedFlagsCallback callBack);

In class e I am trying to call valNamedFlags with

pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::mem_fn(&e::setStatement));

(I started out without the mem_fn() but of course that has the classic "pointers to member functions" problem. I've tried both &e::setStatement and just plain &setStatement.)

FWIW, setStatement is prototyped as

  void setStatement(const int ifcid, const bool isAffirmative);

Everything works if I eliminate the mem_fn() and declare setStatement as static. I'm just pointing that out as a way of saying that I have eliminated all of the other possible issues; my only issue is the "pointers to member functions" problem. Unfortunately, setStatement() needs to be a member function, not a static.

The specific error I am getting in MS VS 2010 is

bool p::valNamedFlags(const OptBlk *,const char *,const int [],const char *[],p::valNamedFlagsCallback)' : cannot convert parameter 5 from 'std::tr1::_Mem_fn3<_Rx,_Pmf,_Arg0,_Arg1,_Arg2>' to 'p::valNamedFlagsCallback'

I would like to keep the callback declaration independent of class e; that is, I do not want to go to

typedef void (*e::valNamedFlagsCallback)(const int, const bool);

because I want to keep p more generalized than that.

Is mem_fn() the right solution or am I way off base? If so, how should I be declaring the callback in the valNamedFlags() prototype?

Or should I be pursuing a different approach?

like image 959
Charles Avatar asked Feb 10 '16 16:02

Charles


People also ask

What is member function in C++?

Next Page. A member function of a class is a function that has its definition or its prototype within the class definition like any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.

What is mem_fn in C++?

Function template std::mem_fn generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers) to an object can be used when invoking a std::mem_fn.

How to declare a function in C?

Like variable in C, we have to declare functions before their first use in program. return_type function_name (type arg1, type arg2 .....); Declaration of a function with multiple input parameter and integer return type.

What is the difference between function declaration and main function?

If function definition is written before main function then function declaration is not required whereas, If function definition is written after main function then we must write function declaration before main function.


2 Answers

Actually, you'll have a problem doing bind-like stuff as some suggested, since your callback is defined as a simple function pointer, and not a callable.

If you can afford to do it, you can change your

typedef void (*valNamedFlagsCallback)(const int, const bool);

to something like

typedef std::function<void(int, bool)> valNamedFlagsCallback

(also noting that const on value parameters doesn't affect the signature of the function), then you can use std::bind(),

using namespace std::placeholders;

pInstance->valNamedFlags(operand,
      "Statement types", 
      statementsSubscripts,
      statementsNames,
      std::bind(&E::setStatement, e, _1, _2));

or you can use lambdas:

pInstance->valNamedFlags(operand,
  "Statement types", 
  statementsSubscripts,
  statementsNames,
  [&](int i, bool b) { e->setStatement(i, b); });

If you must keep it as a simple function, then you'll have to send one which references the right object as a global/static variable.

like image 54
Yam Marcovic Avatar answered Dec 23 '22 05:12

Yam Marcovic


You need to bind an instance on it to call via a member function pointer. (i.e. std::bind(&e::setStatement, eInstance, _1, _2), suppose eInstance is a pointer to an object of class e).

using namespace std::placeholders;  // for _1, _2, _3...
pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::bind(&e::setStatement, eInstance, _1, _2));

Note that the return value of std::bind (which is unspecified) doesn't match the free function pointer type valNamedFlagsCallback, one of the solutions is to use std::function.

typedef std::function<void(const int, const bool)> valNamedFlagsCallback;

Simplified demo

like image 23
songyuanyao Avatar answered Dec 23 '22 06:12

songyuanyao