i'd like to invoke runtime-bound functions of classes, that inherit a binding ability from a common class "Bindable". Is that actually possible?
Here's a stub which surely lacks a lot of template-arguments and namespaces:
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
void bindFunction (int x, auto newFn) {
mFns.insert(std::pair<int, auto>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, function> mFns;
};
class A : Bindable {
void funAone (void) {
cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
cout << "called funAtwo" <<std::endl;
}
};
class B : Bindable {
void funBone (void) {
cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Option #1
Use a CRTP idiom to know what type of pointers to member functions can be stored:
template <typename T>
struct Bindable {
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x,newFn));
}
void invokeFunction (int key) {
(static_cast<T*>(this)->*mFns.at(key))();
}
protected:
std::map<int, void(T::*)()> mFns;
};
struct A : Bindable<A> {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 1
Option #2
Use a type-erasure and make bindFunction a function template:
struct Bindable {
template <typename T, typename std::enable_if<std::is_base_of<Bindable, T>{}, int>::type = 0>
void bindFunction (int x, void(T::*newFn)()) {
mFns.insert(std::make_pair(x, std::bind(newFn, static_cast<T*>(this))));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, std::function<void()>> mFns;
};
struct A : Bindable {
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
DEMO 2
In both cases you can use the code as follows:
int main() {
A a;
B b;
a.bindFunction(1, &A::funAone);
a.bindFunction(2, &A::funAtwo);
b.bindFunction(1, &B::funBone);
b.bindFunction(2, &B::funBtwo);
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Output:
called funAone
called funAtwo
called funBone
called funBtwo
Yes, it's possible, using std::bind. Note that auto can't be used as a function or template argument.
#include <iostream> // std::cout
#include <functional> // std::bind
#include <map> // std::map
class Bindable {
public:
typedef std::function<void()> Function;
void bindFunction (int x, Function newFn) {
mFns.insert(std::pair<int, Function>(x,newFn));
}
void invokeFunction (int key) {
mFns.at(key)();
}
protected:
std::map<int, Function > mFns;
};
class A : public Bindable {
public:
void funAone (void) {
std::cout << "called funAone" <<std::endl;
}
void funAtwo (void) {
std::cout << "called funAtwo" <<std::endl;
}
};
class B : public Bindable {
public:
void funBone (void) {
std::cout << "called funBone" <<std::endl;
}
void funBtwo (void) {
std::cout << "called funBtwo" <<std::endl;
}
};
int main() {
A a;
B b;
a.bindFunction(1, std::bind(&A::funAone, a)); // more than one way to bind
a.bindFunction(2, std::bind(&A::funAtwo, &a)); // the object parameter
b.bindFunction(1, std::bind(&B::funBone, b));
b.bindFunction(2, std::bind(&B::funBtwo, &b));
a.invokeFunction(1);
a.invokeFunction(2);
b.invokeFunction(1);
b.invokeFunction(2);
}
Related
I have a class, classB which has several functions which I would like to specialize based on an enumerator template S.
I have the following example:
#include <iostream>
#include <string>
#include <array>
typedef std::array<double, 3> vec;
enum Op {Op1, Op2, Op3};
template<class T, enum Op S=Op1>
class classA
{
public:
class innerClassA
{
public:
void foo() const
{
std::cout <<"Operation 1" << std::endl;
}
};
};
template<class T>
class classB
{
public:
template <Op S = Op1>
void myFunc()
{
typename classA<T, S>::template innerClassA myInnerClassObj;
for (int i = 0; i < 10; i++)
myInnerClassObj.foo();
}
// Other functions the I would like to able to speciallize afterwards based on template S
void myFunc2() { std::cout << "Func 2" << std::endl; }
void myFunc3() { std::cout << "Func 3" << std::endl; }
};
template<>
void classA<vec, Op2>::innerClassA::foo() const
{
std::cout << "Operation 2" << std::endl;
}
template<>
void classA<vec, Op3>::innerClassA::foo() const
{
std::cout << "Operation 3" << std::endl;
}
int main(int argc, char** argv)
{
classB<vec> obj;
obj.myFunc();
obj.myFunc2();
obj.myFunc<Op2>();
obj.myFunc<Op3>();
return 0;
}
In the above example. The function myFunc has a template parameter based on the enumerator. In the main function, I can call the specialized version based on the value of the enumerator. I would also like to do the same for the other functions,myFunc2 however, always having to put:
template <Op S = Op1>
someFunction()
is quite bothersome. Is there any other way to specify that all functions in a class have a default template based on the enumerator?
Kind regards
No, there is not, apart from macros.
#define OPFUNC template<Op S = Op1> void
OPFUNC myFunc() {}
OPFUNC myFunc2() {}
...
#undef OPFUNC
I have this minimal sample code:
#include <functional>
#include <iostream>
#include <vector>
template<class ReadFileCallback>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback) {
callback("OK");
}
void globalReadResult(std::string result) {
std::cout << "ReadResult in global function: result=" << result << std::endl;
}
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
fileMgr_ReadWithCallback("file", globalReadResult);
//fileMgr_ReadWithCallback("file", this->ReadResult);
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
int main()
{
MyClass c;
c.Read();
return 0;
}
For callback function I'd like to use a non-static class member MyClass::ReadResult. It would also be good to know before calling the callback if the object is still valid (non-destructed), because otherwise the program will fail I guess.
How shall I change this code to be able to use the MyClass object's ReadResult as callback?
You can just wrap it into a lambda:
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
fileMgr_ReadWithCallback("file", [this](const std::string& result){ this->ReadResult(result); });
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
You may use std::bind.
#include <functional>
#include <iostream>
#include <vector>
#include <functional>
template<class ReadFileCallback>
void fileMgr_ReadWithCallback(std::string filename, ReadFileCallback callback) {
callback("OK");
}
void globalReadResult(std::string result) {
std::cout << "ReadResult in global function: result=" << result << std::endl;
}
class MyClass {
public:
MyClass() {};
~MyClass() {};
void Read() {
using std::placeholders::_1;
//std::function<void(std::string)> func = std::bind( &MyClass::ReadResult, this, _1);
auto func = std::bind( &MyClass::ReadResult, this, _1);
fileMgr_ReadWithCallback("file", func);
//
// or
// fileMgr_ReadWithCallback("file", std::bind( &MyClass::ReadResult, this, _1));
}
void ReadResult(std::string result) {
std::cout << "ReadResult in member function: result=" << result << std::endl;
}
};
int main()
{
MyClass c;
c.Read();
return 0;
}
I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor().
Here is my program. I think my main() has some mistake.
#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
void (*successor)()=NULL;
void addSuccessor ( void (*f)() )
{
successor=f;
}
void start()
{
cout<<"In Class"<<endl;
if(!successor==NULL)
successor();
else
cout<<"No Successor"<<endl;
}
};
class Second{
public:
void foo()
{
cout<<"Successor";
}
};
int main()
{
Base obj;
Second obj2;
obj.addSuccessor(&obj2.foo());
obj.start();
}
Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)
class Base {
std::function<void()> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
successor();
} else {
std::cout << "No Successor\n";
}
}
};
Then, you can pass a lambda expression to add_successor:
obj.add_successor([&]{ obj2.foo(); });
(live demo)
As a complement to the discussion above (based on #L.F.'s answer):
#include <functional>
#include <iostream>
#include <utility>
class Base {
std::function<int(int)> successor;
public:
template <typename F>
void add_successor(F&& f)
{
successor = std::forward<F>(f);
}
void start()
{
if (successor) {
auto z = std::invoke(successor, 100);
std::cout << "Output = " << z << "\n";
} else {
std::cout << "No Successor\n";
}
}
};
class Second {
public:
int foo(int x)
{
auto y = x + x;
std::cout << "Successor\n";
return y;
}
};
int main()
{
Base obj;
Second obj2;
obj.add_successor([&](int x)->int { return obj2.foo(x); });
obj.start();
}
In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?
In general, function pointers are used as shown in the code below.
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(A::*BF)();
};
int main()
{
A a;
B b;
b.BF = &A::AF;
(a.*b.BF)();
return 0;
}
I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(* BF)();
};
int main()
{
A a;
B b;
b.BF = a.AF;
return 0;
}
I solved the question through the answer.
Thanks!
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class C {
public:
void CF() { std::cout << "C::F" << std::endl; }
};
class B {
public:
B(){}
std::function<void()> BF;
};
int main() {
A a;
C c;
B b;
b.BF = std::bind(&A::AF, &a);
b.BF();
b.BF = std::bind(&C::CF, &c);
b.BF();
int i;
std::cin >> i;
return 0;
}
What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class B {
public:
B(const std::function<void()>& bf) : BF(bf) {}
std::function<void()> BF;
};
int main() {
A a;
B b1(std::bind(&A::AF, &a)); // using std::bind
B b2([&a] { a.AF(); }); // using a lambda
b1.BF();
b2.BF();
return 0;
}
Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
void AF() { cout << "A::F" << endl; }
void BF() { cout << "B::F" << endl; }
};
class B {
public:
std::function<void()> Delegate;
};
int main() {
A a;
B b;
b.Delegate = std::bind(&A::AF, &a);
b.Delegate();
b.Delegate = [&a] { a.BF(); };
b.Delegate();
return 0;
}
I am trying to achieve the following code pattern.
struct Worker {
void update(/* function pointer */) {
for(unsigned int i = 0; i < 10; i++) {
/* function execution */
}
}
}
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(/*fptr of Derived1::method2*/);
}
}
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
}
I would like to call Derived1's method2 in the instance of Worker::update. How can I define a function pointer that I can inject into the update function.
struct Worker {
void update(/* function pointer */) {
.....
Make Worker::update a template member-function:
struct Worker {
template<typename Func>
void update(Func&& func) {
.....
or use std::function:
struct Worker {
void update(std::function<void()> func) {
.....
Then pass the callback via a lambda in your BaseCrtp<>::method2 as below:
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
Full example:
#include <iostream>
#include <functional>
struct Worker {
template<typename Func>
void update(Func&& func) {
for(unsigned int i = 0; i < 10; i++) {
func();
}
}
//alternatively....
//
//void update(std::function<void()> func) {
// for(unsigned int i = 0; i < 10; i++) {
// func();
// }
//}
};
template <typename t_derive>
struct BaseCrtp {
void method1() {
static_cast<t_derive*>(this)->method1();
}
void method2() {
static_cast<t_derive*>(this)->worker.update(
[this]{ static_cast<t_derive*>(this)->method2(); }
);
}
};
struct Derived1 : public BaseCrtp<Derived1> {
Worker worker;
void method1() {
std::cout << "Derived1::method1" << std::endl;
}
void method2() {
std::cout << "Derived1::method2" << std::endl;
}
};
template<typename T>
void process(BaseCrtp<T>& t){
t.method2();
}
int main(){
Derived1 d1;
process(d1);
}
As seen here or here (std::function alternative).
As Martin Bonner suggested I think you could make use of Worker template with type template parameter containing Derived class and non-type template parameter with a pointer to the method you would like to invoke. This can be done as follows:
template <class T, void (T::*)(void)>
struct Worker {
void update(T *t) {
t->method2();
}
};
struct Foo {
void method2() { }
Worker<Foo, &Foo::method2> worker;
};
int main() {
Foo foo;
foo.worker.update(&foo);
}
[online demo]
This when using compiler optimization should most probably be inlined now which is actually the point of using crtp in a first place:
[godbolt]