C++: Array of member function pointers to different functions - c++

I have a class A which contains member functions foo() and bar() which both return a pointer to class B. How can I declare an array containing the functions foo and bar as a member variable in class A? And how do I call the functions through the array?

The member function pointer syntax is ReturnType (Class::*)(ParameterTypes...), so e.g.:
typedef B* (A::*MemFuncPtr)(); // readability
MemFuncPtr mfs[] = { &A::foo, &A::bar }; // declaring and initializing the array
B* bptr1 = (pointerToA->*mfs[0])(); // call A::foo() through pointer to A
B* bptr2 = (instanceOfA.*mfs[0])(); // call A::foo() through instance of A
See e.g. this InformIT article for more details on pointers to members.
You might also want to look into Boost.Bind and Boost.Function (or their TR1 equivalents) which allow you to opaquely bind the member-function-pointers to an instance:
typedef boost::function<B* ()> BoundMemFunc;
A instanceOfA;
BoundMemFunc mfs[] = {
boost::bind(&A::foo, &instanceOfA),
boost::bind(&A::bar, &instanceOfA)
};
B* bptr = mfs[0](); // call A::foo() on instanceOfA
To use such an array as a member, note that you can't initialize arrays using the member initializer list. Thus you can either assign to it in the constructor body:
A::A {
mfs[0] = &A::foo;
}
... or you use a type that can actually be initialized there like std::vector or boost::array:
struct A {
const std::vector<MemFuncPtr> mfs;
// ...
};
namespace {
std::vector<MemFuncPtr> init_mfs() {
std::vector<MemFuncPtr> mfs;
mfs.push_back(&A::foo);
mfs.push_back(&A::bar);
return mfs;
}
}
A::A() : mfs(init_mfs()) {}

What you're looking for are pointers to member functions. Here is a short sample that shows their declaration and use:
#include <iostream>
class B {
public:
B(int foo): foo_(foo) {
std::cout << "Making a B with foo_ = " << foo_ << std::endl;
}
~B(void) {
std::cout << "Deleting a B with foo_ = " << foo_ << std::endl;
}
int foo_;
};
class A {
public:
A(void) {
funcs_[0] = &A::foo;
funcs_[1] = &A::bar;
}
B* foo(void) {
return new B(3);
}
B* bar(void) {
return new B(5);
}
// Typedef for the member function pointer, for everyone's sanity.
typedef B* (A::*BMemFun)(void);
BMemFun funcs_[2];
};
int main(int argc, char *argv[]) {
A a;
for (int i = 0; i < 2; ++i) {
A::BMemFun func = a.funcs_[i];
// Call through the member function pointer (the .* operator).
B* b = (a.*func)();
delete b;
}
return 0;
}
The C++ FAQ section on pointers to member functions is where I found all this information.

C++ that's not ancient (read: C++11 and later) makes this all easier. In modern C++, you can do
#include <vector>
class B;
class A {
public:
B* foo() {
// return something;
return nullptr;
}
B* bar() {
// return something;
return nullptr;
}
//C++ 11: functional brings std::function, which has zero overhead
//but is actually a useful type with which one can work
std::vector<std::function<B*()>> container;
/* [=]() { return foo(); }
* that's a lambda. In practice it "compiles away", i.e. calling
* the lambda function is the same as calling foo or bar directly
* Note how [=] means we're passing in "this", so that we can
* actually call foo().
*/
A() : container{{[=]() { return foo(); }}, {[=]() { return bar(); }}} {}
};
(Try on godbolt compiler explorer)
Here's a more complete example showcasing what to do with these.
An architectural remark: Be careful with pointers to non-static member functions. What happens if your instance of A gets destroyed, but you still have a function handle to a member function? Right, hell freezes over: There's no object anymore to which this method belongs, so results are catastrophic.

Related

Vector of fn pointers doesn't reveal correct size()

I have a vector of function pointers that is default initialized as a class member, so it always has 2 elements. However, when reading its size() I get gibberish. I have created a trivial, minimal replication of this problem below.
#include <iostream>
#include <vector>
using fnptr = float (*)(float);
float fn1(float x){ return x;};
float fn2(float x){ return x;};
std::vector<fnptr> fnptrs(){
std::vector<fnptr> ret;
ret.push_back(&fn1);
ret.push_back(&fn2);
return ret;
}
class Foo{
public:
int nFns()const{
return fns.size();
}
private:
std::vector<fnptr> fns = fnptrs(); // always initialized
};
class Baz {
public:
explicit Baz(Foo f):foo{&f}{}
const Foo* foo; // my problem does not appear if this is not a pointer
};
class Bar {
public:
explicit Bar(Foo f):foo{f}{
bazs.push_back(Baz(foo));
bazs.push_back(Baz(foo));
}
void viewSizes()const{
for (auto& i:bazs)
std::cout << " i.foo->nFns() = " << i.foo->nFns() << "\n";
}
const Foo foo;
std::vector<Baz> bazs;
};
int main(int argc, const char * argv[]) {
Foo f;
Bar b(f);
b.viewSizes();
return 0;
}
Output:
i.foo->nFns() = -677271344
i.foo->nFns() = -516
I do not prefer to store Foo in Baz as a pointer, but in my real program, I have a vector of Baz's that is swapped out frequently and a reference cannot be used for that (doesn't compile). If I make it a regular member (not a pointer or reference) then I have no problems, but with large numbers of these objects its better not to store the same copy in every object, so a pointer is what I need to use.
Here:
explicit Baz(Foo f):foo{&f}{}
f is a local variable of the constructor and evaporates once the constructor exits. You probably want to pass a reference, or an actual raw pointer instead.

Is there a better/safe way to cast non-const reference of shared_ptr to a base class?

If you have a class Base with virtual methods and a class Implementation which implements the virtual methods, is there any way to cast std::shared_ptr < Implementation > & to std::shared < Base > &? The compiler allows this for const references, but for non const references it fails as in "Case A" in the code below. Is there an easy way to do this?
If not, how safe is my workaround "questionable_cast" in Case B?
#include <iostream>
#include <memory>
class Base
{
public:
virtual void set_value(int x) = 0;
};
class Implementation : public Base
{
public:
Implementation() : m_value(0) { }
void set_value(int x) override
{
m_value = x;
}
int get_value() const
{
return m_value;
}
private:
int m_value;
};
void do_something(std::shared_ptr<Base>& base)
{
base->set_value(5);
/// Code like this makes the non-const argument necessary
base = std::make_shared<Implementation>();
}
template <class T, class U>
std::shared_ptr<T>& questionable_cast(std::shared_ptr<U>& u)
{
/// This code is here to assure the cast is allowed
std::shared_ptr<T> tmp = u;
(void)tmp;
return *reinterpret_cast<std::shared_ptr<T>*>(&u);
}
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
// The following line causes a compiler error:
// invalid initialization of reference of type ‘std::shared_ptr<Base>&’ ...
// do_something(a);
// do_something(std::dynamic_pointer_cast<Base>(a));
// This is the workaround
do_something(questionable_cast<Base>(a));
std::cerr << "a = " << a->get_value() << std::endl;
return 0;
}
Two obvious solutions to the problem as originally asked: 1. Make do_something take a const reference to a shared_ptr (or a shared_ptr by value). 2. Create a named shared_ptr and pass a reference to that: Eg
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
std::shared_ptr<Base> b = a; // This conversion works.
do_something(b); // Pass a reference to b instead.
return 0;
}
Your questionable_cast function is a violation of the strict aliasing rules, and invokes undefined behaviour. It's quite likely to work in initial tests, and then a new release of the compiler will crank up the optimization a notch, and it will fail during a demo.
To handle the case where do_something changes the pointer:
int main()
{
std::shared_ptr<Implementation> a = std::make_shared<Implementation>();
std::shared_ptr<Base> b = a; // This conversion works.
do_something(b); // Pass a reference to b instead.
const auto aa = std::dynamic_pointer_cast<Implementation>(b);
if (aa)
a = aa;
else
; // Handle the error here
return 0;
}
If do_something guarantees to return a pointer of the same derived type, even if it doesn't return the same pointer, wrap it in a template function:
template <typename T>
void do_something_ex( std::shared_ptr<T>& a )
{
std::shared_ptr<Base> b = a;
do_something(b)
a = std::dynamic_pointer_cast<T>(b);
if (!a)
throw_or_assert;
}

C++ - Issue of using function pointer to member function

I've applied solutions based on some search made, but the problem still there. Thank you so much for the help.
error: must use '.*' or '->*' to call pointer-to-member function ...
source code:
#include <stdio.h>
class A
{
public:
struct data;
typedef int (A::*func_t)(data *);
typedef struct data
{
int i;
func_t func;
}
data;
data d;
void process()
{
d.func(&d);
}
A()
{
d.i = 999;
d.func = &A::print;
}
int print(data *d)
{
printf("%d\n", d->i);
return 0;
}
};
int main()
{
A *a = new A;
a->process();
return 0;
}
d.func(&d);
is not enough. func is a member-function-pointer which is pointing to a non-static member of A. So it can be invoked on an object of A. So you need to write this:
(this->*(d.func))(&d);
That would work as long as you write this inside A.
If you want to execute func from outside, say in main(), then the syntax is this:
A a;
(a.*(a.d.func))(&a.d);
That is an ugly syntax.
Your process function attempts to call d.func but it is a pointer to member function. A pointer to member function must be called on some object. Presumably you want the instance of A to be this, in which case your process function should look like:
void process()
{
(this->*(d.func))(&d);
}
Note the use of the ->* operator to call a member function when you have a pointer to it.
Other answers have already said you need to say (this->*d.func)(&d) to call a pointer-to-member function (because you need to provide the object that it's a member of)
Another option is to make the function a static function, which doesn't need special syntax to call. To do that, change the typedef like so:
typedef int (*func_t)(data *);
Then make the print function static:
static int print(data *d)
{
...
}
Now you can just call d.func(&d)
Unfortunately what you are trying to do will not be possible, the reason being that print is not a static member function. This means it expects an implicit first argument that is the this pointer.
I suggest you try using the std::function and std::bind function, something like this:
class A
{
struct data
{
std::function<void(const data&)> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func(d);
}
void print(const data& my_data)
{
std::cout << my_data.i << '\n';
}
};
Of course, since the print function now have a proper this pointer, you no longer need to pass the data structure to it:
class A
{
struct data
{
std::function<void()> func;
int i;
};
data d;
public:
A()
{
d.func = std::bind(&A::print, *this);
d.i = 999;
}
void process()
{
d.func();
}
void print()
{
std::cout << d.i << '\n';
}
};
Calling pointer the members require the class it is a member of to be the this param.
Try:
A a;
a.*(d.func)(&d);

Dynamically create a function pointer that calls a method on a given instance

I suspect this is impossible, but thought I'd ask. Say I have a class with a method:
class A {
public:
void b(int c);
};
I can make a pointer to that member function:
void (A::*ptr)(int) = &A::b;
(someAInstance.*ptr)(123);
I can also abuse function pointers and make a pointer that takes the A argument directly (I don't know if this is safe, but it works on my machine):
void (*ptr2)(A*, int) = (void (*)(A*, int))&A::b;
(*ptr2)(&someAInstance, 123);
What I want is to somehow curry the A argument, and create a function pointer that just takes an int, but calls the A::b method on a particular A instance I've predefined. The A instance will stay constant for that particular function pointer, but there may be several function pointers all pointing to the same A::b method, but using different A instances. For example, I could make a separate wrapper function:
A* someConstantA = new A;
void wrapper(int c) {
someConstantA->b(c);
}
void (*ptr3)(int) = &wrapper;
Now I can use ptr3 without knowing which particular A it's dispatching the call to, but I had to define a special function to handle it. I need a way to make pointers for any number of A instances, so I can't hardcode it like that. Is this in any way possible?
Edit: Should've mentioned, I'm trapped in C++03 land, and also can't use Boost
Don't create a wrapper function, create a wrapper functor. This allows you to encapsulate whatever state you want to (e.g. an A*) in a callable object.
class A {
public:
void b(int c) {}
};
struct wrapper {
A* pA;
void (A::*pF)(int);
void operator()(int c) { (pA->*pF)(c); }
wrapper(A* pA, void(A::*pF)(int)) : pA(pA), pF(pF) {}
};
int main () {
A a1;
A a2;
wrapper w1(&a1, &A::b);
wrapper w2(&a2, &A::b);
w1(3);
w2(7);
}
If you have a sufficiently new compiler (e.g. gcc 4.2+), it should include TR1, where you could use std::tr1::bind:
#include <cstdio>
#include <tr1/functional>
class A {
public:
void b(int c) {
printf("%p, %d\n", (void*)this, c);
}
};
int main() {
A* a = new A;
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1); // <--
f(4);
delete a;
return 0;
}
It is also doable in pure C++03 without TR1, but also much more messier:
std::binder1st<std::mem_fun1_t<void, A, int> > f =
std::bind1st(std::mem_fun(&A::b), a);
You could also write your own function objects.
Note that, in all the above cases, you need to be very careful about the lifetime of a since that is a bare pointer. With std::tr1::bind, you could at least wrap the pointer in a std::tr1::shared_ptr, so that it can live just as long as the function object.
std::tr1::shared_ptr<A> a (new A);
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1);
If you are using C++11, you might use a lambda (untested code):
template<typename T, typename A>
std::function<void(A)> curry(T& object, void (T::*ptr)(A))
{
return [](A a) { (object.*ptr)(std::forward<A>(a)); }
}
I'd be using Boost::bind for this.
Basically:
class A
{
int myMethod(int x)
{
return x*x;
}
};
int main(int argc, char* argv[])
{
A test();
auto callable = boost::bind(&A::myMethod, &A, _1);
// These two lines are equivalent:
cout << "object with 5 is: " << test.myMethod(5) << endl;
cout << "callable with 5 is: " << callable(5) << endl;
return 0;
}
I think that should work. I'm also using auto in here to deduce the type returned by boost::bind() at compile-time, which your compiler may or may not support. See this other question at stackoverflow for an explanation of the return type of bind.
Boost supports back to Visual Studio 2003 (I think) and this all this will work there, though you'll be using BOOST_AUTO I think. See the other question already linked for an explanation.
What you want to do is not possible.
To see why, assume that it is possible - the function pointer must point to a function somewhere in your executable or one of its libraries, so it must point to a function that knows which instance of A to call, much like your wrapper function. Because the instance of A is not known until runtime, you'd have to create those functions at runtime, which isn't possible.
What you're trying to do is possible in C++03, as long as you're happy to pass around a function object rather than a function pointer.
As others have already given solutions with C++11 lambdas, TR1 and boost (all of which are prettier than the below), but you mentioned you can't use C++11, I'll contribute one in pure C++03:
int main()
{
void (A::*ptr)(int) = &A::b;
A someAInstance;
std::binder1st<std::mem_fun1_t<void,A,int> > fnObj =
std::bind1st(std::mem_fun(ptr), &someAInstance);
fnObj(321);
};
I've worked something out with a template Delegate class.
// T is class, R is type of return value, P is type of function parameter
template <class T, class R, class P> class Delegate
{
typedef R (T::*DelegateFn)(P);
private:
DelegateFn func;
public:
Delegate(DelegateFn func)
{
this->func = func;
}
R Invoke(T * object, P v)
{
return ((object)->*(func))(v);
}
};
class A {
private:
int factor;
public:
A(int f) { factor = f; }
int B(int v) { return v * factor; }
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a1 = new A(2);
A * a2 = new A(3);
Delegate<A, int, int> mydelegate(&A::B);
// Invoke a1->B
printf("Result: %d\n", mydelegate.Invoke(a1, 555));
// Invoke a2->B
printf("Result: %d\n", mydelegate.Invoke(a2, 555));
_getch();
delete a1;
delete a2;
return 0;
}

C++: constructor initializer for arrays

I'm having a brain cramp... how do I initialize an array of objects properly in C++?
non-array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Bar {
Foo foo;
Bar() : foo(4) {}
};
array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
// ??? I know the following syntax is wrong, but what's correct?
Baz() : foo[0](4), foo[1](5), foo[2](6) {}
};
edit: Wild & crazy workaround ideas are appreciated, but they won't help me in my case. I'm working on an embedded processor where std::vector and other STL constructs are not available, and the obvious workaround is to make a default constructor and have an explicit init() method that can be called after construction-time, so that I don't have to use initializers at all. (This is one of those cases where I've gotten spoiled by Java's final keyword + flexibility with constructors.)
Edit: see Barry's answer for something more recent, there was no way when I answered but nowadays you are rarely limited to C++98.
There is no way. You need a default constructor for array members and it will be called, afterwards, you can do any initialization you want in the constructor.
Just to update this question for C++11, this is now both possible to do and very natural:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo{{4}, {5}, {6}} { }
};
Those braces can also be elided for an even more concise:
struct Baz {
Foo foo[3];
Baz() : foo{4, 5, 6} { }
};
Which can easily be extended to multi-dimensional arrays too:
struct Baz {
Foo foo[3][2];
Baz() : foo{1, 2, 3, 4, 5, 6} { }
};
Right now, you can't use the initializer list for array members. You're stuck doing it the hard way.
class Baz {
Foo foo[3];
Baz() {
foo[0] = Foo(4);
foo[1] = Foo(5);
foo[2] = Foo(6);
}
};
In C++0x you can write:
class Baz {
Foo foo[3];
Baz() : foo({4, 5, 6}) {}
};
Unfortunately there is no way to initialize array members till C++0x.
You could use a std::vector and push_back the Foo instances in the constructor body.
You could give Foo a default constructor (might be private and making Baz a friend).
You could use an array object that is copyable (boost or std::tr1) and initialize from a static array:
#include <boost/array.hpp>
struct Baz {
boost::array<Foo, 3> foo;
static boost::array<Foo, 3> initFoo;
Baz() : foo(initFoo)
{
}
};
boost::array<Foo, 3> Baz::initFoo = { 4, 5, 6 };
You can use C++0x auto keyword together with template specialization on for example a function named boost::make_array() (similar to make_pair()). For the case of where N is either 1 or 2 arguments we can then write variant A as
namespace boost
{
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
return boost::array<T,2> ({{ a }});
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
return boost::array<T,2> ({{ a, b }});
}
}
and variant B as
namespace boost {
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
boost::array<T,1> x;
x[0] = a;
return x;
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
boost::array<T,2> x;
x[0] = a;
x[1] = b;
return x;
}
}
GCC-4.6 with -std=gnu++0x and -O3 generates the exact same binary code for
auto x = boost::make_array(1,2);
using both A and B as it does for
boost::array<int, 2> x = {{1,2}};
For user defined types (UDT), though, variant B results in an extra copy constructor, which usually slow things down, and should therefore be avoided.
Note that boost::make_array errors when calling it with explicit char array literals as in the following case
auto x = boost::make_array("a","b");
I believe this is a good thing as const char* literals can be deceptive in their use.
Variadic templates, available in GCC since 4.5, can further be used reduce all template specialization boiler-plate code for each N into a single template definition of boost::make_array() defined as
/*! Construct Array from #p a, #p b. */
template <typename T, typename ... R>
boost::array<T,1+sizeof...(R)> make_array(T a, const R & ... b)
{
return boost::array<T,1+sizeof...(R)>({{ a, b... }});
}
This works pretty much as we expect. The first argument determines boost::array template argument T and all other arguments gets converted into T. For some cases this may undesirable, but I'm not sure how if this is possible to specify using variadic templates.
Perhaps boost::make_array() should go into the Boost Libraries?
This seems to work, but I'm not convinced it's right:
#include <iostream>
struct Foo { int x; Foo(int x): x(x) { } };
struct Baz {
Foo foo[3];
static int bar[3];
// Hmm...
Baz() : foo(bar) {}
};
int Baz::bar[3] = {4, 5, 6};
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
Output:
$ make arrayinit -B CXXFLAGS=-pedantic && ./arrayinit
g++ -pedantic arrayinit.cpp -o arrayinit
5
Caveat emptor.
Edit: nope, Comeau rejects it.
Another edit: This is kind of cheating, it just pushes the member-by-member array initialization to a different place. So it still requires Foo to have a default constructor, but if you don't have std::vector then you can implement for yourself the absolute bare minimum you need:
#include <iostream>
struct Foo {
int x;
Foo(int x): x(x) { };
Foo(){}
};
// very stripped-down replacement for vector
struct Three {
Foo data[3];
Three(int d0, int d1, int d2) {
data[0] = d0;
data[1] = d1;
data[2] = d2;
}
Foo &operator[](int idx) { return data[idx]; }
const Foo &operator[](int idx) const { return data[idx]; }
};
struct Baz {
Three foo;
static Three bar;
// construct foo using the copy ctor of Three with bar as parameter.
Baz() : foo(bar) {}
// or get rid of "bar" entirely and do this
Baz(bool) : foo(4,5,6) {}
};
Three Baz::bar(4,5,6);
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
z.foo isn't actually an array, but it looks about as much like one as a vector does. Adding begin() and end() functions to Three is trivial.
Only the default constructor can be called when creating objects in an array.
In the specific case when the array is a data member of the class you can't initialize it in the current version of the language. There's no syntax for that. Either provide a default constructor for array elements or use std::vector.
A standalone array can be initialized with aggregate initializer
Foo foo[3] = { 4, 5, 6 };
but unfortunately there's no corresponding syntax for the constructor initializer list.
There is no array-construction syntax that ca be used in this context, at least not directly. You can accomplish what you're trying to accomplish by something along the lines of:
Bar::Bar()
{
static const int inits [] = {4,5,6};
static const size_t numInits = sizeof(inits)/sizeof(inits[0]);
std::copy(&inits[0],&inits[numInits],foo); // be careful that there are enough slots in foo
}
...but you'll need to give Foo a default constructor.
Ideas from a twisted mind :
class mytwistedclass{
static std::vector<int> initVector;
mytwistedclass()
{
//initialise with initVector[0] and then delete it :-)
}
};
now set this initVector to something u want to before u instantiate an object. Then your objects are initialized with your parameters.
You can do it, but it's not pretty:
#include <iostream>
class A {
int mvalue;
public:
A(int value) : mvalue(value) {}
int value() { return mvalue; }
};
class B {
// TODO: hack that respects alignment of A.. maybe C++14's alignof?
char _hack[sizeof(A[3])];
A* marr;
public:
B() : marr(reinterpret_cast<A*>(_hack)) {
new (&marr[0]) A(5);
new (&marr[1]) A(6);
new (&marr[2]) A(7);
}
A* arr() { return marr; }
};
int main(int argc, char** argv) {
B b;
A* arr = b.arr();
std::cout << arr[0].value() << " " << arr[1].value() << " " << arr[2].value() << "\n";
return 0;
}
If you put this in your code, I hope you have a VERY good reason.
This is my solution for your reference:
struct Foo
{
Foo(){}//used to make compiler happy!
Foo(int x){/*...*/}
};
struct Bar
{
Foo foo[3];
Bar()
{
//initialize foo array here:
for(int i=0;i<3;++i)
{
foo[i]=Foo(4+i);
}
}
};
in visual studio 2012 or above, you can do like this
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo() { }
};
class C
{
static const int myARRAY[10]; // only declaration !!!
public:
C(){}
}
const int C::myARRAY[10]={0,1,2,3,4,5,6,7,8,9}; // here is definition
int main(void)
{
C myObj;
}