I will describe my problem the simplest as I can.
What is my issue:
I have frist class as a singleton:
class CTimer1
{
public:
static CTimer1 * getInstance(); //This gives me pointer to instance
void setChannelA(uint8_t compareValue);
private:
//Cnstructors
CTimer1(); //Prevent consttuction but allow in getInstance
CTimer1(const CTimer1&); //Prevent construction by copying
CTimer1& operator=(const CTimer1&); //Prevent assigment
~CTimer1(); //Prevent unwanted destruction
static CTimer1 * timerInstance;
static bool isCreated;
};
And here is second class where I would like to have possibility to call setChannelA method from CTimer1 class as a setPwm method from CServo class:
class CServo {
public:
CServo();
~CServo();
public:
//public methods
void registerPwmTimer(void (*callback)(uint8_t u8_buffer));
void (*setPwm)(uint8_t u8_buffer); //As this method I would like to call setChannelA from CTimer1 class
};
Here is registerPwmTimer method:
void CServo::registerPwmTimer(void (*callback)(uint8_t u8_buffer))
{
setPwm = callback;
}
Then I have tried to assign pointer to this method as a following:
int main()
{
CTimer1 * timer1 = CTimer1::getInstance();
CServo servo1();
servo1.registerPwmTimer(timer1->setChannelA);
servo1.setPwm(10); //This is example how I want to call setChannelA method
while(1)
{
}
}
I have error:
error: no matching function for call to 'CServo::registerPwmTimer(<unresolved overloaded function type>)'
What is important:
I can't use std::function because this is some part of code in C++ for embedded device, so I need to save memory consumption. Is there any way that I will be able to achieve this effect? If ony one possibility to do this is ot use some std library please for answers too. Thanks for your help.
Your problem is that a function pointer necessarily has to point to a static function. When you invoke an instance function (a method) there is a hidden first argument, which is the object on which the function was invoked. (This hidden argument is available as this within the function's definition.)
Your CServo::registerPwmTimer() function signature is simply incompatible with invocation of a member function; function pointers alone do not provide a way to bind an argument to the pointer, so even if you could convey the member function pointer using a (free) function pointer type, the hidden this argument could not be determined when the function pointer was invoked.
To put it another way, it would fail for the same reason that trying CTimer1::setChannelA(0) would fail -- you want to invoke that method, but you haven't communicated which object on which to invoke it.
Change the signature of CServo::registerPwmTimer to accept an std::function object instead of a raw function pointer. std::function objects can be constructed from function pointers, but they can also be constructed from lambdas, and some standard library functions return function objects:
void registerPwmTimer(std::function<void(uint8_t)>);
Now, you can use std::bind to create a new function that binds the object instance to the member function pointer:
servo1.registerPwmTimer(std::bind(&CTimer1::setChannelA, timer1));
Note that std::bind does not extend the lifetime of the object pointed to by timer1. If the returned function is invoked after that object is destructed, the result is undefined behavior.
Another alternative would be to accept both an instance and a pointer to a member function. The problem with this approach is it requires using templates:
template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
This isn't bad in itself, but what you'll wind up doing is creating a polymorphic wrapper class so that you can insert this into your callback list alongside other callbacks that don't share the same T. At that point, you're just recreating std::function, since std::function already serves the purpose of being a polymorphic wrapper around callable things.
To illustrate the mess of implementing a polymorphic callable wrapper yourself, here is a very light example. I will show the declarations of a set of these types, and link to an example implementation.
This is the base type, with a pure virtual operator() that serves as the invocation operation.
class poly_callable
{
public:
virtual void operator()(int) const = 0;
};
Now we have a type for function pointers (also works with pointer-to-functor):
template <typename T>
class fn_poly_callable : public poly_callable
{
public:
typedef T fn_type;
fn_poly_callable(T);
virtual void operator()(int) const;
private:
T fn;
};
And one for member functions -- oh, but const member functions and non-const member functions are not interchangeable, so we need an extra template parameter for that:
template <typename T, typename M = void (T::*)(int)>
class member_poly_callable : public poly_callable
{
public:
typedef T object_type;
typedef M member_fn_type;
member_poly_callable(member_fn_type, object_type&);
virtual void operator()(int) const;
private:
member_fn_type mfn;
object_type& target;
};
Plus we'll want some helper functions to allow the compiler to infer the template types. One for function pointers:
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(T fn)
{
return std::unique_ptr<poly_callable>(new fn_poly_callable<T>(fn));
}
Two for member functions (const and non-const):
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int), T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T>(mfn, target));
}
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int) const, T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T, void (T::*)(int) const>(mfn, target));
}
If you want to see it all in action, I made a "simple" and working example.
So... just use std::function. There's no reason to reinvent this stuff.
Related
I'm writing a game code using C++. I want to bind the Child's member function into a delegate.
I want to use init_and_bind function like this simplified code:
class Parent {
protected:
Widget* widget;
};
class Child : public Parent {
public:
void foo() {
widget->init_and_bind(this, &Child::bar);
}
void bar() { /* do something */ }
};
I want to implement init_and_bind in Widget class, so I implemented like below code:
// pre-defined in engine
void Delegate::bind(Parent* object, void(Parent::* function)());
void Widget::init_and_bind(Parent* object, void(Parent::* function)()) {
init();
delegate->bind(object, function);
}
But it doesn't work. Because the init_and_bind's second parameter only accepts Parent's member functor type. So I can't pass Child's member functor. So I tried to use template and reinterpret_cast:
template<typename T>
void Widget::init_and_bind(Parent* object, void(T::* function)()) {
init();
delegate->bind(object, function); // error
delegate->bind(object, reinterpret_cast<void(Parent::*)()>(function); // error
}
But it also doesn't work. Because it is failed to cast the Child's functor to Parent's functor.
So, what type should be init_and_bind's second argument?
While the immediate solution is to static_cast, I think you shouldn't turn init_and_bind into a template. The generated code will always be the same pretty much. The only difference is possibly in how the actual cast is performed.
So you'll be getting a fair bit of code bloat, all because of a very small difference. I suggest you encapsulate that difference instead. Add a helper type to Widget for that:
class Widget {
struct MemFunc {
void(Parent::* function)();
template<class T>
MemFunc(void(T::* func)()) :
function(static_cast<void(Parent::*)()>(func))
{}
};
void init_and_bind(Parent* object, MemFunc mf) {
init();
delegate->bind(object, mf.function);
}
};
That way, only the very small piece of code that needs templating is in fact templated. What's best, it's happening transparently on the caller side. And it's probably not even going to cause any bloat. Because your original non-template version required the caller to static_cast anyway.
I'm currently working on a C++ project on the Unreal Engine and I can't wrap my head around this problem.
class A
{
public:
void (* array[10])();
//Add Function to an array
void AddFunctionToArray(void(*function)());
};
class B
{
public:
A a;
//Sending a B function to A
void SendMyFunction();
void Foo();
};
void B::SendMyFunction()
{
a.AddFunctionToArray(&B::Foo);
}
I get the error: can't convert void (B::*)() to void (*)()
How can I send a function pointer from one of my class to another?
void (B::*)() is a pointer to a non-static member function, while void (*)() is a pointer to a non-member function. There is no conversion between the two.
Making B::Foo static would fix this problem. However, you will have no access to instance members of B.
Note that using function pointers, member or non-member, is an old style of passing function objects. A more modern way is using std::function objects, which can be constructed from a combination of an object and one of its member functions.
If you're looking to have class A execute a method from an arbitrary class X you can try this:
template <typename UserClass>
void A::FireMethod(UserClass* InUserObject, typename TMemFunPtrType<false, UserClass, void(int)>::Type InFunc)
{
(InUserObject->*InFunc)(15);
}
In this case we're calling a function with a single int as argument. A class B could do this:
A* a = myAObject;
a->FireMethod(this, &B::MyMethod);
with
void B::MyMethod(int) {}
Hope this helps you! If you want more information, in unreal engine you can look at the AddDynamic macro in Delegate.h
I'm new to C++ and I don't want to use any libraries because I want to really understand whats going on internally.
Additionally I try to keep my library-use as low as possible (to improve performance and) to make it as platform-independent as possible (without exporting the library).
So all in all I'd like to not use std or boost to solve this problem.
My question:
I have an EventHandler which has a function:
template<class T> void EventHandler::SetCallbackFunction(T* obj, void (T::*mem_fkt)(void));
I have to save the object and the function to call it later.
There are 2 possibilities:
EventHandler as template class (and typedef)
void* -> but to call the function I need to cast it back and for that I need the classname :/
Why these dont work:
- The EventHandler can't be a template class because it needs to handle multiple classes..
- void* -> I don't know how to save the classname to cast it later on
How can I do that?
(Or is there another way? Maybe a way to save the classname to cast it later on?)
EDIT:
Furthermore I may need to register multiple callback functions per class so an Interface is not really an option.
class A {
public:
void CallbackFktForEventHandler();
void CallbackFktForAnimationHandler();
etc...
};
And I know that you could solve it based on something like this:
class A{
public:
void Callback();
static void CallbackStatic(void* self){
static_cast<A*>->CallBack();
};
};
But this restricts me too much for my taste.
You could try this:
Create a (pure virtual) base-class that only has one function call():
class Function{
virtual void call()=0;
}
Create a templated class which stores a function-pointer and an object and make it inherit from Function
template<typename T>
class TemplatedFunction{
void (T::*m_fkt)(void);
T* m_obj;
TemplatedFunction(T* obj, void (T::*fkt)(void)):m_fkt(fkt),m_obj(obj){}
void call{
(m_obj->*m_fkt)();
}
}
And then store pointers to Function in your Event-Handler and just use Function->call()
Try it online: http://ideone.com/3Hu5pw
But you will make your life a lot easier if you use at least the standard library. Basically i would use std::bind to bind your object and your member-function together to a function void()(void) and then store these objects inside a std::vector.
Edit: Oktalist was faster ;)
You can use type erasure. You effective save the type of obj by instantiating a class template which implements a non-template virtual interface. This is essentially how std::function is implemented, so you're just writing your own basic version of std::function.
struct ICallback
{
virtual void call() = 0;
};
template <class T>
struct Callback : public ICallback
{
virtual void call() override { (m_obj->*m_func)(); }
Callback(T *obj, void (T::*func)()) : m_obj(obj), m_func(func) {}
T *m_obj;
void (T::*m_func)();
};
template <class T>
std::unique_ptr<ICallback> wrap(T *obj, void (T::*func)())
{
return std::make_unique<Callback<T>>(obj, func);
}
If you don't want to use std::unique_ptr you can roll your own or use an evil raw owning pointer.
I've checked someone's code through a tool, and it said that there is a problem here:
policyCallback = callback;
I cannot find the problem since I'm a beginner.
Could you give me a hint or guide to translate it?
The entire code is below.
std::function <void (std::vector<std::string> resources)> policyCallback;
namepace nsp {
class Manager {
public:
Manager(const std::string &str);
virtual ~Manager();
template <typename FuncType>
void registerPolicyActionCallback(FuncType callback) {
policyCallback = callback;
}
};
} //namespace nsp
namespace nsp{
class Manager;
}
class SomeAPIs {
public:
void policyActionCallback(std::vector<std::string> param);
};
int main() {
nsp::Manager *rManager;
rManager->registerPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, this, std::placeholders::_1));
}
Besides some obvious errors in the code, the main problem preventing you from achieving what you want is the way in which you are calling std::bind.
Firstly, your code declares policyActionCallback(/*...*/) private in SomeAPIs. Now while you can call any member function via a pointer to it, regardless of it being public, protected, or private, only members and friends can create a pointer to a private member function. So unless you call std:bind from within the API itself, or a friend of the API, you will only be able to bind to public member functions of the API. For the sake of demonstrating a working concept, I will assume that the functions you want to use for callback are all public members of the API.
Secondly, to bind a member function using std::bind, you need to provide a reference to the function (which you did), as well a reference (or pointer) to an instance of the class to which the member belongs, which you have not done.
Therefore, since the function you want to bind to is a member of SomeAPIs, you need to give a reference to an instance of SomeAPIs. I'm assuming that you intended this to be a pointer to the nsp::Manager instance, which, as I have just explained, is the wrong object to provide a reference to.
Additionally, your use of the this keyword is incorrect. Taken from cppreference, this can appear in the following contexts
Within the body of any non-static member function, including
member initializer list
Within the declaration of a non-static
member function anywhere after the (optional) cv-qualifier sequence,
including dynamic exception specification(deprecated), noexcept
specification(C++11), and the trailing return type(since C++11)
Within default member initializer (since C++11)
Since your use of this fits non of the above, the compiler gives:
error: invalid use of 'this' in non-member function
Here is working code for what you are wanting to achieve. Note how std::bind is now used. (I have added a constructor for Manager, removed the virtual destructor since manager does not have any virtual function, made the function in SomeAPIs public so that std::bind can receive a pointer to it, and deleted the nsp::Manager pointer which now is declared on the free store):
#include <vector>
#include <iostream>
#include <functional>
std::function <void (std::vector<std::string> resources)> policyCallback;
namespace nsp {
class Manager {
public:
Manager() {};
Manager(const std::string &str) {}
// Don't know why this is virtual when this isn't a base class?
// virtual ~Manager();
template <typename FuncType>
void registerPolicyActionCallback(const FuncType callback) {
policyCallback = callback;
}
};
} //namespace nsp
class SomeAPIs {
public:
void policyActionCallback(std::vector<std::string> param) {
for (const auto& p : param) {
std::cout << "SomeAPIs : " << p << "\n";
}
}
};
// Another API for illustration
class SomeOtherAPI {
public:
void policyActionCallback(std::vector<std::string> param) {
for (const auto& p : param) {
std::cout << "SomeOtherAPI : " << p << "\n";
}
}
};
int main() {
// Sample resource vector for demonstration
std::vector<std::string> resources = {"one", "two", "three"};
// Gets rid of uninitialization error -- alternatively declare on stack
nsp::Manager* rManager = new nsp::Manager;
// You need instances of an object to bind to member functions
SomeAPIs api1;
SomeOtherAPI api2;
// Use the first APIs function as callback
rManager->registerPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, &api1, std::placeholders::_1));
policyCallback(resources);
// Use the second APIs function as callback
rManager->registerPolicyActionCallback(std::bind(&SomeOtherAPI::policyActionCallback, &api2, std::placeholders::_1));
policyCallback(resources);
delete rManager;
}
Here is a live demo.
The snippet you provided is badly extracted copy. It confuses because the line resourceManager->registerUMSPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, this, std::placeholders::_1)); has argument value this, it means it was called inside of a class. There should be pointer to instance of SomeAPIs.
What i meant in the comment is declaration of method registerPolicyActionCallback. It is not necessary to be a template when policyCallback cannot be anything but the only type std::function <void (std::vector<std::string> resources)>;
Anyway all the code looks good. You wrote you used tool to check code, what tool? Does it supports C++11 properly?
I have a question regarding providing a custom delete-method to boost::shared_ptr constructor.
For example, I have a GameObjectFactory class which creates/destroys GameObjects. It has an instance of a MemoryManager, which can Allocate()/Deallocate() memory. CreateObject() returns a GameObject, allocated through the MemoryManager, encapsulated in a boost::shared_ptr.
When the boost::shared_ptr destructs, it should call my MemoryManager->Deallocate() method. However I can't get it right; I get these errors:
error C2276: '&' : illegal operation on bound member function expression
error C2661: 'boost::shared_ptr<T>::shared_ptr' : no overloaded function takes 2 arguments
I have read the boost documentation and the hits I got from stackoverflow, yet I cannot get it right. I dont understand why the below dosnt work.
Here's my code;
#ifndef _I_GAMEOBJECT_MANAGER_H
#define _I_GAMEOBJECT_MANAGER_H
#include "../../Thirdparty/boost_1_49_0/boost/smart_ptr/shared_ptr.hpp"
#include "EngineDefs.h"
#include "IMemoryManager.h"
#include "../Include/Core/GameObject/GameObject.h"
namespace Engine
{
class IGameObjectFactory
{
public:
virtual ~IGameObjectFactory() { }
virtual int32_t Init() = 0;
virtual bool Destroy() = 0;
virtual bool Start() = 0;
virtual bool Stop() = 0;
virtual bool isRunning() = 0;
virtual void Tick() = 0;
template <class T>
inline boost::shared_ptr<T> CreateObject()
{
boost::shared_ptr<T> ptr((T*) mMemoryMgr->Allocate(sizeof(T)),&mMemoryMgr->Deallocate);
return ptr;
}
template <class T>
inline boost::shared_ptr<T> CreateObject(bool UseMemoryPool)
{
boost::shared_ptr<T> ptr((T*) mMemoryMgr->Allocate(sizeof(T),UseMemoryPool), &mMemoryMgr->Deallocate);
return ptr;
}
protected:
IMemoryManager* mMemoryMgr;
};
}
#endif
shared_ptr expects the deleter to be a function that accepts a single argument that is the pointer type (T*). You are trying to pass it a member function, and since shared_ptr has no reference to the IMemoryManager object, it won't work. To get around this, create a static member function that accepts the pointer object and calls IMemoryManager::Deallocate() :
template <class T>
static void Deallocate(T* factoryObject)
{
factoryObject->mMemoryMgr->Deallocate();
}
You can then create your shared_ptr like this:
boost::shared_ptr<T> ptr((T*) mMemoryMgr->Allocate(sizeof(T),UseMemoryPool), &IGameObjectFactory::Deallocate<T>);
boost::shared_ptr, as well as std::shared_ptr takes a predicate as a custom deleter. So you can pass a function, or a functor. What you are passing is a pointer to a member function, which is not enough to invoke it since you don't have a pointer to an object. You have to study Pointers to member functions for details. There are many ways to achieve what you want, I'd write my own simple functor that remembers an object factory pointer, and calls an appropriate method to delete it once invoked by the shared_ptr. Also, consider using intrusive_ptr unless you really need shared_ptr. It is a lot more efficient.