Template and function pointer - c++

Is it somehow possible to store the class from a template without making the the whole class a template?
Task:
I have two functions, v1 without parameters and v2 with parameters,
If v1 was called somewhere nothing happens with Use(), if v2 was called somewhere Use() should execute a function_ptr with the instance I got from DoSometh(T*).
e.g.
class MyClass
{
//v1 no parameters
void DoSomething()
{
}
//v2 with parameter
template<class T>
void DoSomething(T* instance, void (T::*func)())
{
store somewhere?? = instance;
}
void Use()
{
//if DoSometh(T* instance) was used before
if(instance != NULL)
{
(*instance->)//call function pointer from DoSomething(T*,void (T::*)())
}
}
}
std::function problem
update:
class Timer : public ITickable
{
std::function<void()> test; //adding this does weird things
virtual void Tick() {}
}
class MyClass
{
ITickable* tickable_;
void Tick()
{
tickable_->Tick(); //let's assume it points to a Timer obj.
}
}

I think std::function and std::bind (C++11) do accomplish what you want, as already suggested in the comments. A simplified mock-up of your Timer class could be:
class Timer
{
std::function<void()> m_task;
public:
template <typename T>
void setTask(T &instance, void (T::*fcn)()) // consider T const & if applicable
{
m_task = std::bind(fcn, &instance);
}
void fire()
{
if (m_task) // std::function overloads operator bool()
m_task();
}
};
When setTask is called with an object and a member-function that can be called on this object, a std::function object is created (you could choose to do this in a constructor of course). When the timer fires, this object is checked (using operator bool(), provided by std::function), and if it is callable (e.g. when setTask() has been called before), it calls the function.
For example:
class MyClass
{
public:
void func()
{
std::cout << "Hi from MyClass\n";
}
};
class MyOtherClass
{
public:
void func()
{
std::cout << "Hi from MyOtherClass\n";
}
};
int main(int argc, char **argv)
{
MyClass x1;
MyOtherClass x2;
Timer t1, t2;
t1.setTask(x1, &MyClass::func);
t2.setTask(x2, &MyOtherClass::func);
t1.fire();
t2.fire();
}

Related

Can an anonymous lambda function be bound to an object to allow the code in the lambda to access the object's members?

I want to allow a lambda function to access members of an object. There are 2 classes involved here:
The class I want to access
class D {
public:
void doIt() {};
};
An initializer class for management
template<typename T>
class I {
public:
I(std::function<void ()> f) {
someManager->register(this);
_func = f;
}
void run() {
T* t = new T();
auto fn = std::bind(t, _func);
fn();
}
private:
std::function<void ()> _func;
};
static I<D> _init_([]() {
doIt();
});
Then in someManager I'd call: i->run(). However, the call to doIt() is not accepted. What must be changed to make this compile and work?
A working version with fixes:
class D {
public:
void doIt() {};
};
template<typename T>
class I {
public:
I(std::function<void(D*)> f) {
_func = f;
}
void run() {
T* t = new T();
auto fn = std::bind(_func, t);
fn();
// Alternatively.
_func(t);
}
private:
std::function<void(D*)> _func;
};
I<D> _init_([](D* p) {
p->doIt();
});
int main() {
_init_.run();
}
Instead of std::function<void(D*)> you can also use void(*)(D*) because lambda expression [](D* p) { p->doIt();} doesn't capture anything and hence it is convertible to a plain function pointer void(*)(D*).
The code also doesn't need to allocate D on the heap, an automatic object would suffice. E.g.:
void run() {
T t;
_func(&t);
}
You are trying to magic a D into scopes without it being referenced in intervening scopes, and failing. Not only is the lambda invalid, but so is std::bind(t, _func).
Unrelatedly, you are also leaking the Ds you new.
You can construct a std::function<void (T&)> from a void(T::*)() (member with compatible other arguments)
template<typename T>
class I {
public:
I(std::function<void (T&)> f) : _func(f) {
someManager->register(this);
}
void run() {
T t;
_func(t);
}
private:
std::function<void (T&)> _func;
};
static I<D> _init_(&D::doIt);
You need an instance of D to call doIt, so you must pass it to the lamdba somehow:
#include <functional>
class D {
public:
void doIt() {};
};
template<typename T>
class I {
public:
I(std::function<void (T&)> f) {
//someManager->register(this);
_func = f;
}
void run() {
T* t = new T();
_func(*t);
}
private:
std::function<void (T&)> _func;
};
static I<D> _init_([](D& d) {
d.doIt();
});
This should work, however, note that std::function is quite a beast. It encapsulates all kinds of callables. So when you know that you only need member functions then it might be better to store a member function pointer as member.
And note that your run leaks the newed object. I guess that is just for the example, so I didnt fix it here.

Replacing boost::function and boost::bind with Templates

I'm attempting to remove boost libraries from my code.
I don't have std::function, and i'm working with C++98, not c++11. I still need to store a vector of simple void Funcs() from different classes.
I'm using a simple template to get the Class and the instance of the function.
But i'd like to replace the need for boost::function and boost::bind.
class App
{
public:
App();
template<class T>
static void AddLoopFunc(void (T::*func)(), T* instance)
{
loop_funcs.push_back(boost::bind(func, instance));
}
static std::vector< boost::function<void()> > loop_funcs;
};
adding a function to the loop
App::AddLoopFunc(&MyClass::Loop, this);
Let's make some type-erasing adaptor for a member function of any class with a given signature.
struct dummy
{
void func() {};
};
typedef void (dummy::*dummyfunc)();
template <class Obj>
void adapt_ptr_mem_func_0(void* obj, dummyfunc func)
{
void (Obj::*realfunc)() = reinterpret_cast<void (Obj::*)()>(func);
Obj* realobj = reinterpret_cast<Obj*>(obj);
(realobj->*realfunc)();
}
You can call a pointer-to-member-function of any class with this. Not in a type safe manner but we will hide this behind a type-safe store front in a moment.
class callback
{
void (dummy::*func)();
void* obj;
void (*adaptor)(void*, void (dummy::*)());
public:
template <class Obj>
callback(Obj* obj, void (Obj::*func)(void)) :
obj(obj), func(reinterpret_cast<dummyfunc>(func)),
adaptor(adapt_ptr_mem_func_0<Obj>) {}
void operator()()
{
adaptor(obj, func);
}
};
The callback constructor accepts an object obj_ and a pointer-to-member-function func_, and makes a type-erased function object that, when called, calls (obj->*func)().
Testing:
struct Moo
{
int m;
Moo (int m) : m(m) {};
void doit() { std::cout << m << "\n"; }
};
int main()
{
Moo moo(42);
callback c(&moo, &Moo::doit);
c();
};
boost::function and boost::bind are available in C++98, no need to replace them.

C++ passing unknown type to a virtual function

I'm writing in C++ and I want to pass an unknown type (known only in run time) to a pure virtual function:
virtual void DoSomething(??? data);
where DoSomething is an implementation of a pure virtual function in a derived class.
I planned to use templates but as it turn out virtual function and templates don't work together: Can a C++ class member function template be virtual?
I want to avoid using a base class for all the classes I pass to the function (something like object in C#).
Thanks in advance
You need type erasure. An example of this is the general purpose boost::any(and std::any in C++17).
virtual void DoSomething(boost::any const& data);
And then each sub-class can attempt the safe any_cast in order to get the data it expects.
void DoSomething(boost::any const& data) {
auto p = any_cast<std::string>(&data);
if(p) {
// do something with the string pointer we extracted
}
}
You can of course roll out your own type erasing abstraction if the range of behaviors you seek is more constrained.
If you do not want to use boost/C++17 any, consider deriving the parameter of 'doSometing' function from a base class, and do dynamic cast to the right class object. In this case you can check in runtime that you got a valid pointer.
class param{
public:
virtual ~param(){};
};
template <typename T>
struct specificParam:param{
specificParam(T p):param(p){}
T param;
};
class Foo
{
public:
virtual void doSomething(param* data) = 0;
};
template <typename T>
class Bar : public Foo
{
public:
virtual void doSomething(param* data){
specificParam<T> *p = dynamic_cast<specificParam<T> *>(data);
if (p != nullptr){
std::cout<<"Bar got:" << p->param << "\n";
}
else {
std::cout<<"Bar: parameter type error.\n";
}
}
};
int main(){
Bar<char> obj1;
Bar<int> obj2;
Bar<float> obj3;
specificParam<char> t1('a');
specificParam<int> t2(1);
specificParam<float> t3(2.2);
obj1.doSomething(&t1); //Bar got:a
obj2.doSomething(&t2); //Bar got:1
obj3.doSomething(&t3); //Bar got:2.2
// trying to access int object with float parameter
obj2.doSomething(&t3); //Bar: parameter type error.
}
The simplest (but unsafe!) way would be to use void* pointer + static cast
class Foo
{
public:
virtual void doSomething(void* data) = 0;
};
template <typename T>
class Bar:public Foo
{
public:
virtual void doSomething(void* data){
T* pData = static_cast<T*>(data);
std::cout<<"Bar1 got:" << *pData << "\n";
}
};
int main(){
Bar<char> obj1;
Bar<int> obj2;
Bar<float> obj3;
char c = 'a';
int i = 1;
float f = 2.2;
obj1.doSomething(&c); // Bar1 got:a
obj2.doSomething(&i); // Bar1 got:1
obj3.doSomething(&f); // Bar1 got:2.2
//obj2.doSomething(&c); // Very bad!!!
}
Type-erasure is not the only possibility.
You may be interested to use the visitor pattern: take as argument an std::variant and visit it with a lambda containing the template code you wanted to implement:
virtual void doSomething(std::variant<int,float/*,...*/> data)
{
visit([=](auto v){/*...*/;},data);
}
something like that?:
class Foo
{
virtual ~Foo() = 0;
};
template <typename T>
class Bar : public Foo
{
T object;
}
...
virtual void DoSomething(Foo* data)
{
Bar<int>* temp = dynamic_cast<Bar<int>*>(data);
if (temp)
std::count<<temp->object;
}

Pass method as callback from one class to other class

I have 2 class, I would like to pass a method from one to other by callback!
See that I also wish to hold the address of this method using void (*callBack)();
I'm used to do this in C, but I dont know how to do this in c++;
#include <iostream>
using namespace std;
class A
{
private:
void (*callBack)(); //to hold the address of the method
public:
A();
void setCallBack(void(*cB)());
void useCallBack();
};
A::A()
{
}
void A::setCallBack(void(*cB)())
{
callBack = cB;
}
void A::useCallBack()
{
callBack();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(someMethod);
Aguy->useCallBack()
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
The problem is that:
void (*callBack)();
This is not a pointer to a method. This is a pointer to a function.
To have a pointer to a method you need to specify the class the method is in.
void (B::*callBack)();
Then when you call it you need to call it via an object.
void A::useCallBack(B* b)
{
(b->*callBack)();
}
But this is probably not what you want.
What you really want is a wrapper that encapsulates all this.
I would take a look at std::function. This will allow you to wrap a method call and an object into a single object that you can then call.
std::function<void()> callback;
Just replace all your occurrences of void(*cB)() with std::function<void()> then you can bind an instance of the object to the method at the call point.
Aguy->setCallBack(std::bind(&B::someMethod, this));
This also allows you to seemly pass any normal function or functor as a callback.
void print()
{ std:cout << "It worked\n";
}
...
Aguy->setCallBack(&print);
struct Printer
{
void operator()() const
{
std::cout << "It worked with obejct\n";
}
}
...
Aguy->setCallBack(Printer());
If you need to pass member function pointers see the modified code. it uses modern c++ constructs.
#include <iostream>
#include <functional>
using namespace std;
class A
{
private:
typedef std::function<void()> some_void_function_type;
some_void_function_type f_;
public:
A();
void setCallBack(some_void_function_type f);
void useCallBack();
};
A::A()
{
}
void A::setCallBack(some_void_function_type f)
{
f_ = f;
}
void A::useCallBack()
{
f_();
}
class B
{
private:
A * Aguy;
public:
B();
void someMethod();
void otherMethod();
};
B::B()
{
Aguy = new A();
}
void B::otherMethod()
{
Aguy->setCallBack(std::bind(&B::someMethod, this));
Aguy->useCallBack();
}
void B::someMethod()
{
cout << "Hello. I'm from class b" << endl;
}
int main()
{
B Bguy;
Bguy.otherMethod();
return 0;
}
See c++ - <unresolved overloaded function type> for details.
To quote the answer:
In C++, member functions have an implicit parameter which points to
the object (the this pointer inside the member function). Normal C
functions can be thought of as having a different calling convention
from member functions, so the types of their pointers
(pointer-to-member-function vs pointer-to-function) are different and
incompatible. C++ introduces a new type of pointer, called a
pointer-to-member, which can be invoked only by providing an object.
Put static on someMethod:
class B
{
private:
A * Aguy;
public:
B();
static void someMethod();
void otherMethod();
};
void B::otherMethod() {
Aguy->setCallBack(B::someMethod);
Aguy->useCallBack(); // adding missing semicolon
}

Calling template pointer to member function

Im working on a GUI and i want to be able to pass function pointers to my buttons, however, these could be called from different kinds of classes, which is why i made it use templates.
I do believe it stores the function pointer correctly but i cannot call it correctly.
class MainMenuScene: public Scene
{
public:
void add_button(){
void (MainMenuScene::*func)();
func = &MainMenuScene::test;
Button b(func);
b.click();
}
void test();
private:
GUI<MainMenuScene> gui;
};
template<class T>
class Button: public GUI_object{
public:
Button(void (T::*func)());
void click(){
func_();
private:
void (T::*func_)();
};
This is the error i get:
Button.h|23|error: must use '.*' or '->*' to call pointer-to-member function
in '((Button<MainMenuScene>*)this)->Button<MainMenuScene>::func_ (...)',
e.g. '(... ->* ((Button<MainMenuScene>*)this)->Button<MainMenuScene>::func_) (...)'|
The function that you store a pointer to is not a static function so you need an object instance to call it.
Something like this maybe:
class MainMenuScene: public Scene
{
public:
void add_button(){
void (MainMenuScene::*func)();
func = &MainMenuScene::test;
Button<MainMenuScene> b(this, func);
b.click();
}
void test();
private:
GUI<MainMenuScene> gui;
};
template<class T>
class Button: public GUI_object{
public:
Button(T* obj, void (T::*func)());
void click(){
(obj_->*func_)(); }
private:
void (T::*func_)();
T* obj_;
};
A member function pointer must be used on a specific object. For example, in your case you would need a MainMenuScene object on which to call your function pointer.
Example:
class MainMenuScene
{
public:
void test() {
std::cout << "Hello!" << std::endl;
}
};
int main()
{
void (MainMenuScene::*myPointerToMember)() = &MainMenuScene::test;
MainMenuScene myObj{};
MainMenuScene* myObjP = &myObj;
(myObj.*myPointerToMember)(); //Parentheses around (myObj.*myPointerToMember) are important
(myObjP->*myPointerToMember)();
}