array of pointers to class method error c++11 - c++

I got a small "problem" with array of pointers to class method.
In short:
My class Complex has four functions - double funX(void):
double fun1(void) const {...}
double fun2(void) const {...}
...
Then I have and array of pointers to member functions of above recipe.
double (Complex::*arr_ptr_fun[4])(void) const;
I initialize this array in constructor initializer list:
... : re(_re), im(_im), arr_ptr_fun{&fun1,&fun2,&fun3,&fun4} { /*EMPTY*/ }
When I try to call any of these 4 functions via this array e.g.:
std::cout << this->*arr_ptr_fun[0]();
I get an error I do not understand:
error: must use '.*' or '->*' to call pointer-to-member function in '((const Complex*)this)->Complex::arr_ptr_fun[0] (...)', e.g. '(... ->* ((const Complex*)this)->Complex::arr_ptr_fun[0]) (...)'
double fun4(void) const {std::cout << this->*arr_ptr_fun[0](); return sqrt(fun3());}
Use .* or ->* via which pointer...? (chaos * Universe pointer?)
Any ideas?

You need to surround the member function pointer in parenthesis,
std::cout << (this->*arr_ptr_fun[0])();

The answer given by #Aldehir is the correct answer to your specific question. However, if you are using C++11 (or later) then it might be a lot more convenient to use std::mem_fn to wrap calls to member functions. Using std::mem_fn you can eliminate the issues associated with .* and ->*. Here is an example:
#include <iostream>
#include <functional>
#include <array>
class Complex
{
public:
double fun1() const {return 1;}
double fun2() const {return 2;}
double fun3() const {return 3;}
double fun4() const {return 4;}
using MemFun = decltype(std::mem_fn(&Complex::fun1)) ;
static const std::array<MemFun, 4> arr_ptr_fun ;
} ;
const std::array<Complex::MemFun, 4> Complex::arr_ptr_fun {{
std::mem_fn(&Complex::fun1),
std::mem_fn(&Complex::fun2),
std::mem_fn(&Complex::fun3),
std::mem_fn(&Complex::fun4)
}} ;
int main()
{
//
// Call all the member functions using object my_foo.
//
Complex my_foo ;
for(auto func: Complex::arr_ptr_fun)
{
std::cout << func(my_foo) << std::endl;
}
//
// The same as above but using array indexing.
//
for(size_t i=0; i<Complex::arr_ptr_fun.size(); ++i)
{
std::cout << Complex::arr_ptr_fun[i](my_foo) << std::endl ;
}
return 0;
}

Related

Get reference to member function overloaded by const specification

Here is some class with two overloaded methods foo:
class Object {
public:
Object (double someVal) : val(someVal) { }
double getter () const { return val; }
double& getter () { return val; }
private:
double val;
};
So now the double Object::getter() const function will be called on const instances
const Object instance(42);
cout << instance.getter() << endl; // called: `double getter() const`
Now, I am trying to get reference to double getter() const function and assign it to std::function type
const Object instance(42);
function<double(const Object&)> foo = &Object::getter;
cout << foo(instance) << endl;
The code works fine if function double& getter() is removed, but with it I got the following error on the second line:
test.cpp:18:34: error: no viable conversion from '<overloaded function type>' to
'function<double (const Object &)>'
function<double(const Object&)> foo = &Object::getter;
^ ~~~~~~~~~~~~~~~
It seems that error happens, because system tries to call double& getter().
The question is how to force calling of double getter() const?
The full listing is attached here
By casting to the specific function pointer type:
std::function<double(const Object&)> foo = static_cast<double(Object::*)() const>(&Object::getter);
Just use a lambda closure:
Object o{0.0};
std::function<double()> f = [o](){ return o.getter(); };
The lambda calls the const version of getter(), as captured variables are const by default (otherwise you'd have to use mutable).
Address of Overload functions defined 7 contexts where the correct overload can be deduced. Yet std::function<...> is not one of them. Thus, the overload function to get address of is ambiguous.
There are a few ways to select the overload you want:
const Object instance(42);
// Use static_cast to select overload
std::function<double(const Object&)> foo = static_cast<double(Object::*)() const>(&Object::getter);
// Use lambda to select overload
// std::function type parameters can be omitted since c++ 17
// Guaranteed copy elision since c++ 17
std::function bar = [](const Object& instance) { return instance.getter(); };
// Use std::mem_fn
std::function<double(const Object&)> mfn = std::mem_fn<double() const>(&Object::getter);
However, an idiomatic way to declare methods with similar functionality but differed by constness is actually to declare two different functions: foo() and cfoo(). Think about begin() and cbegin(). The latter returns a const iterator.
You can use a typedef to disambiguate the function you want:
#include <iostream>
#include <functional>
class Object {
public:
Object (double someVal) : val(someVal) { }
double getter () const { return val; }
double& getter () { return val; }
private:
double val;
};
typedef double (Object::*funtype)() const;
int main()
{
const Object instance(42);
std::function<double(const Object&)> foo = static_cast<funtype>(&Object::getter);
std::cout << foo(instance) << std::endl;
}
run on cpp.sh
Or, without casting:
#include <iostream>
#include <functional>
class Object {
public:
Object (double someVal) : val(someVal) { }
double getter () const { return val; }
double& getter () { return val; }
private:
double val;
};
typedef double (Object::*funtype)() const;
int main()
{
const Object instance(42);
funtype temp = &Object::getter;
std::function<double(const Object&)> foo = temp;
std::cout << foo(instance) << std::endl;
}
run on cpp.sh
Yet another example, going through some options.
// auto mem_fn = static_cast<double (Object::*)() const>(&Object::getter);
// or shorter:
double (Object::*mem_fn)() const = &Object::getter;
// store member function (without instance)
std::function<double(const Object&)> foo = mem_fn;
std::cout << foo(instance) << "\n";
// bind with instance
auto bound = std::bind(mem_fn, &instance);
std::cout << bound() << "\n";
// store member function (with instance)
std::function<double()> bar = bound;
std::cout << bar() << "\n";
// store member function (with instance), without the intermediate steps
std::function<double()> baz =
std::bind(
static_cast<double (Object::*)() const>(&Object::getter),
instance
);
std::cout << baz() << "\n";

Is it safe to cast between a function pointer and a member function pointer? [duplicate]

I've inherited some C++ code and I've been tasked with getting rid of warnings.
Here we have a member function pointer being cast to a function pointer.
I understand that member function pointers are "different" from function pointers, in that there is an implicit 'this' parameter involved under the hood. However my predecessor appears to have made explicit use of this fact, by casting from a member function pointer to a function pointer with an additional first parameter inserted.
My Questions are:
A) Can I get rid of the compiler warning?
B) To what extent is this code guaranteed to work?
I've cut it down to a small main.cpp for the purposes of this question:
#define GENERIC_FUNC_TYPE void(*)(void)
#define FUNC_TYPE int(*)(void *)
class MyClass
{
public:
MyClass(int a) : memberA(a) {}
int myMemberFunc()
{
return memberA;
}
private:
int memberA;
};
int main(int argc, char*argv[])
{
int (MyClass::* memberFunc) () = &MyClass::myMemberFunc;
MyClass myObject(1);
std::cout << (myObject.*memberFunc)() << std::endl;
// All good so far
// Now get naughty, store it away in a very basic fn ptr
void(*myStoredFunction)(void) = (GENERIC_FUNC_TYPE)memberFunc; // Compiler warning
// Reinterpret the fn pointer as a pointer to fn, with an extra object parameter
int (*myExtractedFunction)(void*) = (FUNC_TYPE)myStoredFunction;
// Call it
std::cout << myExtractedFunction(&myObject) << std::endl;
}
The code compiles with one warning under g++, and as intended outputs two 1's:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:27:53: warning: converting from ‘int (MyClass::*)()’ to ‘void (*)()’ [-Wpmf-conversions]
void(*myStoredFunction)(void) = (GENERIC_FUNC_TYPE)memberFunc; // Compiler warning
^
IMHO this code is making assumptions about the underlying mechanisms of the compiler. Or maybe these assumptions are valid for all C++ compilers - Can anyone help?
(In the actual code we're storing a whole bunch of function pointers by name in a map. These functions all have different signatures, which is why they are all cast to the same signature void(*)(void). This is analogous to the myStoredFunction above. They are then cast to the individual signatures at the point of calling, analogous to myExtractedFunction above.)
How about create functions which avoid the cast entirely:
template <typename C, void (C::*M)()>
void AsFunc(void* p)
{
(static_cast<C*>(p)->*M)();
}
then
void (*myExtractedFunction)(void*) = &AsFunc<MyClass, &MyClass::myMemberFunc>;
In C++17, with some traits, you might even have template <auto *M> void AsFunc(void* p) and void(*myStoredFunction)(void*) = &AsFunc<&MyClass::myMemberFunc>;
To answer the question in the title, no, you can't legally cast a pointer-to-member-function to a pointer-to-function. Presumably, that's what the "Compiler warning" on the line with that cast said.
A conforming compiler is required to issue a diagnostic when confronted with ill-formed code (that's a bit oversimplified), and this one did. It gave a warning. Having done that, the compiler is free to do something implementation-specific, which it seems to have done: it compiled the code into something that does what you were hoping for.
Compilers are free to represent pointers to member functions in any way that works, and for non-virtual functions, that could be just a "normal" pointer to function. But try that with a virtual function; I'll bet the consequences are more harsh.
A) Can I get rid of the compiler warning?
Yes - wrap the member function in a call from a static function
(This is a low-tech variant of #Jarod42's template based answer)
B) To what extent is this code guaranteed to work?
It's not (summarizing #Pete Becker's answer). Until you get rid of the warning.
Here's the jist of what we went with. We kept it simple to minimize disruption to the code. We avoided advanced C++ features to maximize the number of people who can work on the code.
#include <iostream>
class MyClass
{
public:
MyClass(int a) : memberA(a) {}
static int myMemberFuncStatic(MyClass *obj)
{
return obj->myMemberFunc();
}
int myMemberFunc()
{
return memberA;
}
private:
int memberA;
};
typedef void(*GENERIC_FUNC_TYPE)(void);
typedef int(*FUNC_TYPE)(MyClass *);
int main(int argc, char*argv[])
{
int (* staticFunc) (MyClass *) = &MyClass::myMemberFuncStatic;
MyClass myObject(1);
std::cout << staticFunc(&myObject) << std::endl;
// All good so far
// This is actually legal, for non-member functions (like static functions)
GENERIC_FUNC_TYPE myStoredFunction = reinterpret_cast<GENERIC_FUNC_TYPE> (staticFunc); // No compiler warning
// Reinterpret the fn pointer as the static function
int (*myExtractedFunction)(MyClass*) = (FUNC_TYPE)myStoredFunction;
// Call it
std::cout << myExtractedFunction(&myObject) << std::endl;
}
Since you apparently need to call a function by name on some "untyped" object (void*) while passing in a number of arguments that differ by function, you need some kind of multiple-dispatch. A possible solution is:
#include <string>
#include <iostream>
#include <stdexcept>
#include <functional>
#include <utility>
#include <map>
template <typename Subj>
using FunctionMap = std::map<std::string, std::function<void (Subj&, const std::string&)>>;
class AbstractBaseSubject {
public:
virtual void invoke (const std::string& fName, const std::string& arg) = 0;
};
template <typename Class>
class BaseSubject : public AbstractBaseSubject {
public:
virtual void invoke (const std::string& fName, const std::string& arg) {
const FunctionMap<Class>& m = Class::functionMap;
auto iter = m.find (fName);
if (iter == m.end ())
throw std::invalid_argument ("Unknown function \"" + fName + "\"");
iter->second (*static_cast<Class*> (this), arg);
}
};
class Cat : public BaseSubject<Cat> {
public:
Cat (const std::string& name) : name(name) {}
void meow (const std::string& arg) {
std::cout << "Cat(" << name << "): meow (" << arg << ")\n";
}
static const FunctionMap<Cat> functionMap;
private:
std::string name;
};
const FunctionMap<Cat> Cat::functionMap = {
{ "meow", [] (Cat& cat, const std::string& arg) { cat.meow (arg); } }
};
class Dog : public BaseSubject<Dog> {
public:
Dog (int age) : age(age) {}
void bark (float arg) {
std::cout << "Dog(" << age << "): bark (" << arg << ")\n";
}
static const FunctionMap<Dog> functionMap;
private:
int age;
};
const FunctionMap<Dog> Dog::functionMap = {
{ "bark", [] (Dog& dog, const std::string& arg) { dog.bark (std::stof (arg)); }}
};
int main () {
Cat cat ("Mr. Snuggles");
Dog dog (7);
AbstractBaseSubject& abstractDog = dog; // Just to demonstrate that the calls work from the base class.
AbstractBaseSubject& abstractCat = cat;
abstractCat.invoke ("meow", "Please feed me");
abstractDog.invoke ("bark", "3.14");
try {
abstractCat.invoke ("bark", "3.14");
} catch (const std::invalid_argument& ex) {
std::cerr << ex.what () << std::endl;
}
try {
abstractCat.invoke ("quack", "3.14");
} catch (const std::invalid_argument& ex) {
std::cerr << ex.what () << std::endl;
}
try {
abstractDog.invoke ("bark", "This is not a number");
} catch (const std::invalid_argument& ex) {
std::cerr << ex.what () << std::endl;
}
}
Here, all classes with functions to be called this way need to derive from BaseSubject (which is a CRTP). These classes (here: Cat and Dog, let's call them "subjects") have different functions with different arguments (bark and meow - of course more than one function per subject is possible). Each subject has its own map of string-to-function. These functions are not function pointers, but std::function<void (SubjectType&,const std::string&)> instances. Each of those should call the respective member function of the object, passing in the needed arguments. The arguments need to come from some kind of generic data representation - here, I chose a simple std::string. It might be a JSON or XML object depending on where your data comes from. The std::function instances need to deserialize the data and pass it as arguments. The map is created as a static variable in each subject class, where the std::function instances are populated with lambdas. The BaseSubject class looks up the function instance and calls it. Since the subject class should always directly derive from BaseSubject<Subject>, pointers of type BaseSubject<Subject>* may be directly and safely cast to Subject*.
Note that there is no unsafe cast at all - it is all handled by virtual functions. Therefore, this should be perfectly portable. Having one map per subject class is typing-intensive, but allows you to have identically-named functions in different classes. Since some kind of data-unpacking for each function individually is necessary anyways, we have individual unpacking-lambdas inside the map.
If a function's arguments are just the abstract data structure, i.e. const std::string&, we could leave the lambdas out and just do:
const FunctionMap<Cat> Cat::functionMap = {
{ "meow", &Cat::meow }
};
Which works by way of std::functions magic (passing this via the 1st argument), which, in contrast to function pointers, is well-defined and allowed. This would be particularly useful if all functions have the same signature. In fact, we could then even leave out the std::function and plug in Jarod42's suggestion.
PS: Just for fun, here's an example where casting a member-function-pointer to an function-pointer fails:
#include <iostream>
struct A {
char x;
A () : x('A') {}
void foo () {
std::cout << "A::foo() x=" << x << std::endl;
}
};
struct B {
char x;
B () : x('B') {}
void foo () {
std::cout << "B::foo() x=" << x << std::endl;
}
};
struct X : A, B {
};
int main () {
void (B::*memPtr) () = &B::foo;
void (*funPtr) (X*) = reinterpret_cast<void (*)(X*)> (memPtr); // Illegal!
X x;
(x.*memPtr) ();
funPtr (&x);
}
On my machine, this prints:
B::foo() x=B
B::foo() x=A
The B class shouldn't be able to print "x=A"! This happens because member-function pointers carry an extra offset that is added to this before the call, in case multiple inheritance comes into play. Casting loses this offset. So, when calling the casted function pointer, this automatically refers to the first base object, while B is the second, printing the wrong value.
PPS: For even more fun:
If we plug in Jarod42's suggestion:
template <typename C, void (C::*M)(), typename Obj>
void AsFunc (Obj* p) {
(p->*M)();
}
int main () {
void (*funPtr) (X*) = AsFunc<B, &B::foo, X>;
X x;
funPtr (&x);
}
the program correctly prints:
B::foo() x=B
If we look at the disassembly of AsFunc, we see:
c90 <void AsFunc<B, &B::foo, X>(X*)>:
c90: 48 83 c7 01 add $0x1,%rdi
c94: e9 07 ff ff ff jmpq ba0 <B::foo()>
The compiler automatically generated code that adds 1 to the this pointer, such that B::foo is called with this pointing to the B base class of X. To make this happen in the AsFunc function (opposed to buried within main), I introduced the Obj template parameter which lets the p argument be of the derived type X such that AsFunc has to do the adding.

How can I make a C++ member function by binding the arguments of another member function?

I am having problems with creating a variable of pointer-to-member-function (PTMF) type "on the fly" (that is, by pinning some arguments of an existing member function via std::bind). My question is if it is ever possible with C++11 or post-C++11 standard.
Preambula: I have a class that stores a static const array of std::functions initialized from PTMFs, hereinafter referred to as "handlers". Originally, they were regular member functions with a name and implementation so I didn't ever use C++11 and std::function. Then, I decided that many of them are nearly similar, and decided to generate them with a "generator function". I would like to avoid using templates for the generation because the number of these nearly similar handlers is going to dramatically increase in future (around 200+) and templatizing will just lead to code bloat.
If the PTMFs in question were static, I would have no problems with generating the handlers via std::bind. A simplified example:
#include <iostream>
#include <functional>
using namespace std;
struct A {
typedef function<void(int)> HandlerFn;
static void parametrized_handler(int i, const char *param) {
cout << "parametrized handler: " << param << endl;
}
static void handler(int i) { cout << "handler 1" << endl; }
int mm;
};
static const A::HandlerFn handler2 = [](int) { cout << "handler 2" << endl; };
static const A::HandlerFn handler3 = bind(A::parametrized_handler,
placeholders::_1,
"test_param");
int main()
{
A::handler(42);
handler2(42);
handler3(42);
return 0;
}
Output:
$ ./a.out
handler 1
handler 2
parametrized handler: test_param
The problem arises when I turn to non-static member functions. std::bind is not able to generate a function object that acts like a PTMF. I know that I can pass a real object as a first argument to bind and get a working function but that is not what I want: when I am initializing a static const array, there are no objects at all, and the result of bind will act as a regular non-member function anyway.
An expected implementation for non-static member functions (with an imaginary std::bind_mem binder):
#include <iostream>
#include <functional>
using namespace std;
struct A;
struct A {
typedef function<void(int)> HandlerFn;
void parametrized_handler(int i, const char *param) {
mm;
cout << "parametrized handler: " << param << endl;
}
void handler(int i) const { mm; cout << "handler 1" << endl; }
const HandlerFn handler2 = [this](int i) { mm; cout << "handler 2" << endl; };
int mm;
};
// An imaginary PTMF binder
// static const A::HandlerFn handler3 = bind_mem(A::parametrized_handler,
// placeholders::_1,
// "test_param");
int main()
{
A a;
(a.handler)(42);
(a.handler2)(42);
//(a.handler3)(42);
return 0;
}
Output:
$ ./a.out
handler 1
handler 2
So is there a way to implement a PTMF argument binding?
For binding a pointer to non static member function, you need an object.
#include<functional>
struct A {
typedef std::function<void(int)> HandlerFn;
void mem(int);
void static static_mem(int);
};
void foo() {
A a;
A::HandlerFn h1 = A::static_mem;
//This captures a by ref
A::HandlerFn h2 = std::bind(&A::mem, std::ref(a), std::placeholders::_1);
//This captures a by copy
A::HandlerFn h3 = std::bind(&A::mem, a, std::placeholders::_1);
//Change to =a for copy
A::HandlerFn h4 = [&a](int i){
a.mem(i);
};
h1(34);
h2(42);
}
Link:https://godbolt.org/g/Mddexq

Class non-static method pointer to global function

I'm trying to point a class method to a global function, i've seen this
but how i can't do it without instance?.
Consider this:
class x
{
public:
int(x::*GetVal)(int);
};
int RtX(int a)
{
return a * 4;
}
// declaration
int(x::*GetVal)(int) = (int(x::*)(int))&::Rtx; // :: global? // error
int main()
{
x a;
cout << (a.*GetVal)(4) << endl;
}
This returns me the error:
[Error] invalid cast from type 'int ()(int)' to type 'int
(x::)(int)'
x::GetX is a pointer to member. These are deeply complicated beasts, and you can't get them to point to non-member functions. The following code will work:
#include <iostream>
int RtX(int a) // Global non-member function
{
return a * 4;
}
class x
{
public:
int(x::*GetVal)(int);
// This is an instance member function which acts as a proxy and calls the
// the global function
int RtX(int a) { return ::RtX(a); }
};
int main()
{
x a;
a.GetVal =&x.RtX; // Assign the member variable. Could do this in the
// constructor. **NOTE** No casts!
std::cout << (a.*GetVal)(4) << std::endl;
}
If you find yourself reaching for a cast when dealing with function pointers and pointers-to-member-functions, stop - you are almost certainly doing it wrong, and while it will compile, it is very likely not to run properly.
Alternatively, as noted in the comments, use std::function.
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
std::function<int(int)> GetVal;
// Initialize GetVal in the constructor.
x() : GetVal(RtX)
{}
// Alternatively, you can initialize the variable in with a default
// initialization. You can also declare the member const if you don't want to
// change it later.
const std::function<int(int)> gv = RtX;
/*
};
int main()
{
x a;
std::cout << a.GetVal(4) << std::endl;
}
Non static member functions need an instance in order to be called. You might consider using a static function member instead and if you also use std::function, you might get a simple code to assign your member function without instance:
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
static std::function<int(int)> GetVal;
};
std::function<int(int)> x::GetVal = RtX;
int main()
{
x a;
std::cout << (a.GetVal)(4) << std::endl;
}

Setting a pointer to a non-static member function

I'm trying to setup a function pointer that is set during execution based on a set of user parameters. I would like to have the function pointer point to a non-static member function but I can't find how to do it.
The examples I've seen say this can only be done with static member function only or use global variables in straight C.
A simplified example follows:
class CA
{
public:
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(double f(const double), double x) {
char cTemp[256];
sprintf_s(cTemp, "Value = %f", f(x));
std::cout << cTemp;
};
private:
double a, b;
};
The implementation part is
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (*p)(const double);
if(true) {
p = &cA.getA; //'&' : illegal operation on bound member function expression
} else {
p = cA.getB; //'CA::getB': function call missing argument list; use '&CA::getB' to create a pointer to member
//'=' : cannot convert from 'double (__thiscall CA::* )(const double)' to 'double (__cdecl *)(const double)'
}
cA.print(p, 3.0);
So how do I get p to point to either 'getA' or 'getB' so that it is still useable by 'print'.
From what I have seen, the suggestions are to use boost or std::bind but I've had no experience with either of these. I'm hoping that I don't need to dive into these and that I'm just missing something.
Compiler MSVC++ 2008
Don't forget that a member function accepts an implicit this parameter: therefore, a member function accepting a double can't be the same thing as a non-member (free) function accepting a double.
// OK for global functions
double (*p)(const double);
// OK for member functions
double (CA:*p)(const double);
Also the way you invoke them is different. First of all, with member functions, you need an object to invoke them on (its address will eventually be bound to the this pointer in the function call). Second, you need to use the .* operator (or the ->* operator if you are performing the call through a pointer):
p = &CA::getA;
CA cA;
(cA.*p)();
Consistently, you will have to change your definition of function print():
#include <iostream>
void print(double (CA::*f)(const double), double x)
{
// Rather use the C++ I/O Library if you can...
std::cout << "Value = " << (this->*f)(x);
};
So finally, this is how you should rewrite your main() function:
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (CA::*p)(const double);
if (true) // Maybe use some more exciting condition :-)
{
p = &CA::getA;
}
else {
p = &CA::getB;
}
cA.print(p, 3.0);
}
Compilation Issue
This answer focuses on the compilation issue presented in the question. I would not recommend implementing this as a solution.
Pointers to member functions are best dealt with with typedefs and a macro.
Here's the macro for calling a member function:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
Source: [33.6] How can I avoid syntax errors when calling a member function using a pointer-to-member-function?, C++ FAQ.
This saves you having to remember the ugly (object).*(ptrToMember) syntax any time you wish to call a member function by pointer.
In your class, declare a typedef called CAGetter, this will make variable declaration much simpler:
class CA
{
public:
typedef double (CA::*CAGetter)(const double x);
Then you can declare your print() function quite simply:
void print(CAGetter f, double x)
The body is also simple, clear and concise:
{
std::cout << "value = " << CALL_MEMBER_FN(*this, f)(x) << '\n';
}
Sample usage:
CA a;
a.setA(3.1);
a.setB(4.2);
// Using a variable...
CA::CAGetter p = &CA::getA;
a.print(p, 1);
// without a variable
a.print(&CA::getB, 1);
// Calling the functions from outside the class...
std::cout << "From outside (A): " << CALL_MEMBER_FN(a, p)(10) << std::endl;
std::cout << "From outside (B): " << CALL_MEMBER_FN(a, &CA::getB)(10) << std::endl;
Design Issue
Passing a pointer to a member function into a method of an instance of the same class is a design smell (you wouldn't normally pass a member variable to a method, this is no different). There is not enough information in this question to address the underlying design issue but this problem could probably be solved with separate print() methods, a member variable or with inheritance and polymorphism.
You can either use pointer to method:
class CA
{
public:
typedef double (CA::*getter)( double );
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(getter f, double x) {
char cTemp[256];
sprintf(cTemp, "Value = %f", (this->*f)(x));
std::cout << cTemp;
};
private:
double a, b;
};
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
CA::getter p;
if(true) {
p = &CA::getA;
} else {
p = &CA::getB;
cA.print( p, 3.0 );
}
Or use boost::bind
class CA
{
public:
typedef boost::function<double( double )> getter;
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(getter f, double x) {
char cTemp[256];
sprintf(cTemp, "Value = %f", f(x));
std::cout << cTemp;
};
private:
double a, b;
};
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
CA::getter p;
if(true) {
p = boost::bind( &CA::getA, &cA, _1 );
} else {
p = boost::bind( &CA::getB, &cA, _1 );
}
cA.print( p, 3.0 );
}