How to create a map of <id, member function>? - c++

I have the following code in which I create a map of pointers to member functions.
class A {
public:
A() {
m[0] = &A::F1;
m[1] = &A::F2;
}
void F1(int v) { ... }
void F2(int v) { ... }
void O(int i, int v) {
(*m[i])(v);
}
private:
using func = void(A::*)(int);
std::map<int, func> m;
};
But there is a compiling error in "O". In my understanding, "m[i]" is a pointer to member function, (*m[i]) dereferences it and should call the corresponding member function. But it does not work.
Could you please help to explain it?
Are there other neat ways to create a map of member functions?

The pointer to a member function only holds the pointer to the function, but not to the object on which it should be called.
You need to call that member function on an object:
(this->*m[i])(v);

Another way you could accomplish the same (arguably easier to read than plain function pointers) is with std::function, example:
class A {
public:
A() { // implicit capture of this is deprecated in c++20
m[0] = [this](int v) { F1(v); };
m[1] = [this](int v) { F2(v); };
}
void F1(int v) { std::cout << "F1: " << v; }
void F2(int v) { std::cout << "F2: " << v; }
void O (int i, int v) { m[i](v); }
private:
std::map<int, std::function<void(int)>> m;
};
int main() {
A a;
a.O(0, 5);
}

Related

lambda expression using scope variables - is safe?

When f is called, a is already "destructed". Is it safe to use it this way? How does it work?
std::function<void()> f;
{
int a = some_calc();
f = [=] { std::cout << a << std::endl; }
}
f();
Is it safe to use it this way?
Yes
How does it work?
The closure object created by that lambda expression has int a as a data member, copy-initialised from the a in that scope.
Here is conceptually what is going on:
#include <functional>
#include <iostream>
int some_calc() {
// ...
return 42;
}
int main() {
std::function<void()> f;
{
int a = some_calc();
class Lambda {
private:
int a;
public:
Lambda(int const& _a) : a{_a} {}
void operator()() const { std::cout << a << std::endl; }
};
f = Lambda{a};
}
f();
}

How to call object's methods using a function pointer?

I'd like to call a few methods of classes 'A' and 'B' from the class 'Caller'. I need to use a function pointer because I want to call different methods.
My method gets called, but when I try to access a member variable from it, my program crashes ('program.exe has stopped working').
How come that happens?
#include <iostream>
using namespace std;
template <class T>
class Caller
{
typedef void (T::*myFunc)(int);
public:
Caller(T* obj, myFunc fp)
{
f = fp;
}
void invoke(int foobar)
{
(o->*f)(foobar);
}
private:
myFunc f;
T* o;
};
class A
{
public:
A() : n(0) {}
void foo(int bar)
{
cout << "A::foo called (bar = " << bar << ", n = " << n << ")" << endl; // the crash occurs here, and 'this' equals 0 at this point
}
void setNum(int num)
{
n = num;
}
private:
int n;
};
class B
{
public:
B() : n(0) {}
void fooo(int bar)
{
cout << "B::fooo called (bar = " << bar << ", n = " << n << ")" << endl; // same here if I call B::fooo first
}
void setNum(int num)
{
n = num;
}
private:
int n;
};
int main()
{
A myA;
B myB;
myA.setNum(128);
myB.setNum(256);
Caller<A> cA(&myA, &A::foo);
Caller<B> cB(&myB, &B::fooo);
cA.invoke(10);
cB.invoke(20);
return 0;
}
Thank you in advance.
EDIT : I use VS2017 and I can build my program without getting any compiler errors.
My method gets called, but when I try to access a member variable from it, my program crashes ...
Because you forgot to assign passed obj to o pointer in your Caller:
template <class T>
class Caller
{
typedef void (T::*myFunc)(int);
public:
Caller(T* obj, myFunc fp)
{
o = obj; // << == you need this!
f = fp;
}
void invoke(int foobar)
{
(o->*f)(foobar);
}
private:
myFunc f;
T* o;
};
Also, in general it's better to use member initializer lists:
Caller::Caller(T* obj, myFunc fp) : o(obj), f(fp)
{
}

Avoid the class scope so as to pass a member function as a function pointer

I'll describe my question using the following sample code.
I have class B defined as follows:
class B
{
public:
inline B(){}
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(int (*f)(int x)) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
int(*myfunc)(int);
};
I then define class A as follows:
class A
{
public:
A(int myint) :a{ myint }{ b.setfunction(g); }
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
To me the issue seems to be that the member function g has the signature int A::g(int) rather than int g(int).
Is there a standard way to make the above work? I guess this is quite a general setup, in that we have a class (class B) that contains some sort of member functions that perform some operations, and we have a class (class A) that needs to use a particular member function of class B -- so is it that my design is wrong, and if so whats the best way to express this idea?
You can use std::function:
class B
{
public:
inline B() {}
inline B(std::function<int(int)> f) : myfunc{ f } {}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction([this](int a) {
return g(a);
}
);
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
You could generalize the class B. Instead of keeping a pointer (int(*)(int)), what you really want is any thing that I can call with an int and get back another int. C++11 introduced a type-erased function objection for exactly this reason: std::function<int(int)>:
class B
{
using F = std::function<int(int)>
public:
B(){}
B(F f) : myfunc(std::move(f)) { }
void setfunction(F f) { myfunc = std::move(f); }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
F myfunc;
};
And then you can just provide a general callable into B from A:
A(int myint)
: b([this](int a){ return g(a); })
, a{ myint }
{ }
Use std::function and std::bind
class B
{
public:
inline B(int(*f)(int)) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
// ...
A a;
B b(std::bind(&A::g, &a));
Also note that you should initialize the function pointer to some default value (most likely null) and check for it when using, otherwise it's value is undefined.
You could use std::bind to bind the member function A::g.
class B
{
public:
inline B(){}
inline B(std::function<int(int)> f) :myfunc{ f }{}
void setfunction(std::function<int(int)> f) { myfunc = f; }
void print(int number) { std::cout << myfunc(number) << std::endl; }
private:
std::function<int(int)> myfunc;
};
class A
{
public:
A(int myint) :a{ myint } {
b.setfunction(std::bind(&A::g, this, std::placeholders::_1));
}
int g(int) { return a; }
void print() { b.print(a); }
private:
B b;
int a;
};
Note you need to change the type of functor from function pointer to std::function, which is applicable with std::bind.
LIVE

Can I give function pointer to template parameter?

Can I do something like this?
template<function_pointer_type pointer_name> struct structure1{
//here I call pointer_name(0)
};
void* function1 = [&](int a) {
return a * a;
}
structure1<function1> b;
I tried but it never compiled.
So, what's wrong with the code?
function1 is not constant expression so it cannot be used as template argument.
The lambda is not convertible to function pointer because it has a non-empty capture list.
Instead of function pointer, I suggest using a template parameter of function object, or std::function.
Function object:
template <class FunctionObject>
class A
{
private:
FunctionObject fun;
public:
A(FunctionObject f) : fun(f) {}
void f() { cout << fun(5) << endl; }
};
template <class FunctionObject>
A<FunctionObject> make_A(FunctionObject f)
{
return A<FunctionObject>(f);
}
std::function:
template <class FunctionType>
struct B
{
std::function<FunctionType> fun;
};
The usage:
void usage()
{
auto a = make_A([](int a) {return a*a; });
a.f();
B<int(int)> b;
b.fun = [&](int a) {return a*a; };
cout << b.fun(10) << endl;
}
To make this as absolutely similar to your original question as possible (using a lambda and a templated structure and so on):
#include <iostream>
template<typename F>
struct structure1 {
structure1(F x) : f(x) {}
int operator() (int a) { return f(a); };
F f;
};
int(*function1)(int) = [&](int a) {
return a * a;
};
int main() {
structure1< int(*)(int) > x(function1);
std::cout << x(4) << std::endl;
return 0;
}
I compiled and tested this with g++ -std=c++11 test.cpp

functor call (additional characters)

I tried to build a minimal example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}
My question about this: Why is it even possible to call the operator on the pure type without an object? How can I call the function other the same way as I call operator()?
You're not calling it on a pure type. foo() invokes the constructor, and evaluates to a temporary foo object, on which you then invoke operator().
To do the equivalent with a "normal" member function, just do:
foo().other(a);
You are not "call[ing] the operator on the pure type without an object". The syntax foo()(a) is creating a temporary of type foo (this is the foo() part) and then calling operator() on that object with a as argument: (the (a) part).
Pure type example:
struct Functor
{
void operator()(int& a)
{
a += 1;
}
void other(int& a)
{
a += 2;
}
static void one_more(int& a)
{
a += 3;
}
};
template <typename foo>
class Class
{
public:
void function()
{
int a = 10;
foo()(a);
foo().other(a);
foo::one_more(a);
std::cout << a << std::endl;
}
};
int main()
{
Class<Functor> c;
c.function();
}