Custom deleter for boost shared_ptr - c++

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.

Related

Passing Inherited Class's Member Functor

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.

Method of one class as callback from another

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.

Could you explain the mixture of many kinds of operands below? (C++)

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?

C++ error: A reference of type cannot be initialized with a value of type

Hi I got a problem I can't find a solution to. I'm creating a entity - component system with smart pointers.
The error I get is:
a reference of type std::unique_ptr<PrimaryComponent, std::default_delete<PrimaryComponent>> & (not const-qualified) cannot be initialized with a value of type std::unique_ptr<PlayerGraphics, std::default_delete<PlayerGraphics>>
The gameworld class:
auto GameWorld::Setup_World() -> void
{
player->Attach_Component(player_Graphics);
Add_GameObject(player);
}
The gameobject class attach component function:
void GameObject::Attach_Component(std::unique_ptr<PrimaryComponent> &component)
{
if (component != nullptr)
{
component_container.push_back(component);
}
}
The declaration of player_Graphics and player:
class GameWorld
{
private:
std::vector<std::unique_ptr<GameObject>> gameObject_List;
std::unique_ptr<GameObject> player;
std::unique_ptr<PlayerGraphics> player_Graphics
player is a GameObject, player_Graphics is a Graphics Component which derives from PrimaryComponent.
The primary component class:
class PrimaryComponent
{
protected:
public:
PrimaryComponent();
virtual ~PrimaryComponent();
virtual void Render(GameObject &gameObject) = 0;
virtual void Update(GameObject &gameObject, GameWorld &gameWorld, float gameTime) = 0;
};
The PlayerGraphics class:
class PlayerGraphics :
public GraphicsComponent
{
public:
PlayerGraphics();
virtual ~PlayerGraphics();
virtual void Render(GameObject &gameObject);
virtual void Update(GameObject &gameObject, GameWorld &gameWorld, float gameTime);
};
PlayerGraphics derives from GraphicsComponent which derives from PrimaryComponent.
The problem is in the reference:
The line:
void GameObject::Attach_Component(std::unique_ptr<PrimaryComponent> &component)
should be:
void GameObject::Attach_Component(std::unique_ptr<PrimaryComponent> component)
And then, when you call it, instead of:
player->Attach_Component(player_Graphics);
you should do:
player->Attach_Component(std::move(player_Graphics));
That is, the function should take ownership of the pointer. Note that the original player_Graphics will be set to null (you moved it in, if you want to keep a reference ot that object then you are using the wrong tool).
You may be wondering why in your code passing a std::unique_ptr<PrimaryComponent> directly works, but passing a std::unique_ptr<PlayerGraphics> does not. Well the explanation is that you are using a non-const reference, and non-const references can only bind to an object of the exact same time. However if you pass the argument by value, then the smart pointer will be moved and it all will just work.
This all makes sense, std::unique_ptr is meant to be non-copyable, non-shareable, moveable smart pointers. You are expected to move the pointer around, not to pass it by reference.
TL;DR: If B is a subclass of A you can move a std::unique_ptr<B> into a std::unique_ptr<A> but you cannot bind a std::unique_ptr<B> to a reference of type std::unique_ptr<a>&.
PS. The constructor to move&cast is declared as follows:
template <class T, class D = default_delete<T>>
class unique_ptr
{
template <class U, class E>
unique_ptr (unique_ptr<U,E>&& x) noexcept;
};
It looks like you are calling GameObject::Attach_Component with the wrong type. It wants a std::unique_ptr<PrimaryComponent> but you are passing it a std::unique_ptr<PlayerGraphics>
EDIT
It doesn't matter if PlayerGraphics derives from PrimaryComponent. That won't work with smart pointers, only raw pointers.

Using arbitrary owning pointer without templating

I would like to pass (shared) ownership of an object to a function foo::bar.
The thing is I do not care, whether the ownership is exclusive or shared.
I see class foo as an interface where I do not want to care about the ownership details.
All I care about is that I can secure the lifetime of the passed smart pointer beyond the return of foo::bar.
Now I could write
class foo {
void bar( std::shared_ptr<blub> );
void bar( std::unique_ptr<blub> );
};
but this is unelegant in times where we have accumulated several smart pointer variants.
And writing an overload for every variant is quite cumbersome, especially if I want to use this scheme multiple times in my code.
Now I also do not want foo to be templated, for the obvious template complexities.
The simplest I can come up with would be a smart pointer wrapper
template <typename T>
class owning_ptr {
// Sorts out the largest type so we can allocate enough space
typedef largest<std::shared_ptr<T>, std::unique_ptr<T>, myptr<T>>::type big_type;
typedef std::aligned_storage <sizeof(big_type), std::alignment_of<big_type>::value>::type buffer_type;
buffer_type _internal;
int _type;
};
which is a bit inefficient. Is there a better way to construct the wrapper?
In the end I would really like to have the signature:
class foo {
void bar( owning_ptr<blub> );
};
Note: There's an interesting EDIT at the bottom
If you don't want to parameterize or overload on the owning pointer type, you're probably best off taking a shared_ptr<> and forcing a conversion for unique_ptr<>. Any non-template solution I can think of would have at least the same amount of overhead as a shared_ptr, most requiring a polymorphic call, a free-store allocation, or both.
You might be able to automate the conversion from shared_ptr by taking some type of proxy converter, which should allow you to take either a unique_ptr R-value or a shared_ptr without a cast or explicit conversion (other than move()) and extract a usable shared_ptr to store in your instance. Here's an example:
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
// Take an instance of gimme_owned_ptr<T> to save off a shared_ptr<T>
// from either a shared_ptr or unique_ptr.
template<typename T>
struct gimme_owned_ptr {
// Make the two constructors templates so we can accept
// any convertible owning pointer:
template<typename S>
gimme_owned_ptr( unique_ptr<S> p )
: p_( shared_ptr<S>( move(p) ) )
{ }
template<typename S>
gimme_owned_ptr( shared_ptr<S> p )
: p_( p )
{ }
shared_ptr<T> get() const {
return p_;
}
private:
shared_ptr<T> p_;
};
struct Foo {
void operator()() const { v_call(); }
virtual ~Foo() { }
private:
virtual void v_call() const = 0;
};
struct Bar {
Bar( gimme_owned_ptr<Foo const> const &gop )
: foo_( gop.get() )
{ }
void operator()() const { (*foo_)(); }
private:
shared_ptr<Foo const> foo_;
};
struct Baz : Foo {
private:
virtual void v_call() const { cout << "Baz()()\n"; }
};
int main() {
unique_ptr<Baz> upf( new Baz() );
shared_ptr<Baz> spf( new Baz() );
Bar upb( move( upf ) );
Bar spb( spf );
upb();
spb();
}
Yes, this solution does use templates, but only for the gimme_owned_ptr utility class template, and only for re-use and conversion. Your own class (Bar in this case) wouldn't need to be a template, nor would you need to re-implement gimme_owned_ptr to use it with another type.
======== EDIT ========
I just checked, and the built-in conversion from unique_ptr to shared_ptr essentially does everything the gimme_owned_ptr class I wrote above. If the class takes a type of shared_ptr<T>, passing a move(unique_ptr<S>) will result in a workable conversion. So, all you really need is to take a shared_ptr and the only thing the user should have to do is call move() on unique_ptrs (which they should be doing anyway). The only reason to use something like gimme_owned_ptr would be to accept a different mixture of pointers or accept them in a different way. (For example, you could make the move() unnecessary by taking a unique_ptr<S>& and calling move() internally, but this is probably a bad idea as it will silently seize ownership.)