I have a ServiceProvider class which contains a couple of pointers to different services, like that:
class ServiceProvider()
{
Service3* GetService3();
public:
void Process(Object* o);
void Shrink();
private:
TAutoSpawningPtr<Service1> service1;
TAutoSpawningPtr<Service2> service2;
Service3* service3;
}
Note that TAutoSpawningPtr is a theoretical smart pointer сlass I'm looking for, and service3 is declared as an ordinary pointer to explicitly show the behaviour I needed.
The body of Process():
void ServiceProvider::Process(Object* o)
{
service1->Process(o);
service2->Process(o);
GetService3()->Process(o);
}
The body of GetService3():
void ServiceProvider::GetService3()
{
if(!service3)
{
service3 = new Service3();
}
return service3;
}
As you can see, an instance of Service3 is being created lazily and it don't exist until it needed.
Shrink() method is being called periodically to delete all internal services. Like this:
void ServiceProvider::Shrink()
{
service1.Release(); // delete its internal Service1 pointer if it exists.
service2.Release(); // delete its internal Service2 pointer if it exists.
if (service3)
{
// delete its internal Service3 pointer if it exists.
delete service3;
service3 = nullptr;
}
}
What do I need: I want TAutoSpawningPtr<> to be a smart pointer class, which automatically creates its class instance by calling the default construcror once I dereference the pointer using an overloaded operator->. An inner resource posessed by the pointer had to be deleted once called the Release() method (and, of course, it had to be recreated when I need it again).
Why do I need this?
To automatically control presence/absence of an object.
To prevent nullptrs when derefenecing pointers directly (like this->service3->Process(o)) instead of indirect GetService3().
To release unused services without explicit checks.
The question is: Does the standard (or any third-party) library have an auto pointer class which will satisfy my needs? And if not, would you kindly to bring me some code examples that shows behavior I need. Thanks.
The simplest solution here would be to just call a function that initializes the two if they are uninitialized or are not pointing to anything.
But if you really want to, you can create a simple proxy pointer class that does this for you. For example
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
class Something {
public:
Something() {
cout << __PRETTY_FUNCTION__ << endl;
}
void do_something() {
cout << __PRETTY_FUNCTION__ << endl;
}
};
template <typename Type,
template <typename...> class Ptr = std::unique_ptr>
class AutoAllocatingPtr {
public:
Type* operator->() {
if (!this->ptr) {
this->ptr = Ptr<Type>{new Type{}};
}
return this->ptr.get();
}
void release() {
this->ptr.reset();
}
private:
Ptr<Type> ptr;
};
int main() {
// default unique ownership with std::unique_ptr
auto ptr = AutoAllocatingPtr<Something>{};
ptr->do_something();
ptr.release();
ptr->do_something();
// if you want shared ownership
auto s_ptr = AutoAllocatingPtr<Something, std::shared_ptr>{};
s_ptr->do_something();
s_ptr.release();
s_ptr->do_something();
}
Note Note the code in the end and how you can use that to switch the type of ownership semantics that the pointer exhibits.
Related
I have two classes,
template<class Type>
class SafePtr {
public:
SafePtr() {}
~SafePtr() {}
void Lock(Type* data, void* key)
{
if (!pKey)
{
pKey = key;
pData = data;
}
}
Type* Unlock(void* key) const
{
if (key == pKey)
return pData;
}
Type* operator->()
{
return pData;
}
private:
Type* pData = nullptr;
void* pKey = nullptr;
};
template<class Type>
class SafePtrArray {
public:
SafePtrArray() {}
~SafePtrArray() {}
template<class... Args>
SafePtr<Type> CreatePtr(Args&&... args)
{
Type* data = new Type(args...);
ptrs.insert(ptrs.end(), data);
SafePtr<Type> ptr;
ptr.Lock(data, this);
return ptr;
}
Type* UnlockPtr(const SafePtr<int>& ptr)
{
return ptr.Unlock(this);
}
void Destroy(const SafePtr<int>& ptr)
{
Type* pointer = ptr.Unlock(this);
for (auto itr = ptrs.begin(); itr != ptrs.end(); itr++)
{
if ((*itr) == pointer)
{
delete pointer;
ptrs.erase(itr);
}
}
}
private:
std::vector<Type*> ptrs;
};
The goal is to protect a pointer so that the user can access its members but not get to manipulate its actual pointer (mainly delete it prematurely). And also I need to store all the pointers in an array so that when the parent object destroys, I can automatically destroy all the allocated pointers
For this I use two classes, SafePtr and SafePtrArray. SafePtrArray creates and stores the pointers and wraps them in the SafePtr and returns it to the user. SafePtr is just a wrapper and should not let the user get access to the underlying pointer but will allow them to access its members.
It works fine at first but soon I found this error,
int main()
{
SafePtrArray<int> ptr;
auto pInt = ptr.CreatePtr();
int* i = pInt.operator->(); // Users can get access to the underlying pointer using this.
ptr.Destroy(pInt);
}
Is there a way to prevent users from getting access to the underlying type and prevent them from manipulating the pointer while having the privilege to access its members?
I still think you try to solve a problem that has more to do with possible flaws in the design of the API/of the code, the documentation, or with the lack of C++ knowledge of the one using it, with a "solution" that has more cons than pros.
If a C++ programmer does not know what ownership is or does not respect it and blindly deletes objects or frees the memory of pointers, then there will be much bigger concerns. You likely will move the problem just to a different part of the code.
Having that said, the closest you can do to not expose the pointer right now is something like this:
(The code is just a proof of concept, so things like call might need to be improved)
#include <iostream>
#include <string>
struct Test {
void foo(int x, int y, std::string str) {
std::cout << x << " " << y << " " << str << std::endl;
}
double test = 0.5;
};
template <typename T>
struct Ptr {
template <auto M, typename... Args>
auto call(Args... args) {
return (obj.*M)(std::forward<Args>(args)...);
}
template <auto M>
auto get() {
return (obj.*M);
}
protected:
T obj;
};
int main() {
Ptr<Test> p;
p.call<&Test::foo>(1, 2, "hello");
std::cout << p.get<&Test::test>() << std::endl;
return 0;
}
But I still don't think that this is a good approach.
And a user can still mess around with the code and do something bad like:
int main() {
Ptr<Test> p;
delete &p;
return 0;
}
Or this, which for sure is undefined behavior, but that does not really matter as deleting a not owned object will also result in undefined behavior at some point:
template<typename T>
struct Ptr {
protected:
T *obj;
}
template<typename T>
struct Ptr2 {
public:
T *obj;
};
int main()
{
Ptr<Test> p;
Ptr2<Test> *p2 = reinterpret_cast<Ptr2<Test>*>(&p);
std::cout << p2->obj << std::endl;
}
So there is no protection again such things.
Besides the shown code, there is a proposal for reflection that is feature complete now, which would allow getting information about the members of a type, but this was not added to c++20, and one for metaclasses which is also not in the standard yet.
With these two proposals, you might be able to implement something better useable. But my concerns about the benefits of this remain.
Is there a way to prevent users from getting access to the underlying type and prevent them from manipulating the pointer while having the privilege to access its members?
Under certain conditions, no, this is not possible. If the underlying Type is a standard layout class then providing access to the first non-static non-bitfield data member breaks your goal. (Caveat: providing access to just the value of the member is a different story.) The address of that member can be converted to a pointer to the underlying object via reinterpret_cast, which allows calling delete on that pointer. (Well, "allows" in the sense that the call is syntactically valid. Not much else matters for "allows" since we are headed into undefined behavior anyway.)
For classes that are not standard layout, there are probably compiler-specific (non-portable) methods to achieve the same effect (converting the address of a data member into a pointer to the underlying object). There is no reason for a compiler to try actively to thwart such things.
If a programmer is determined to invoke undefined behavior, there is little you can do to stop it.
Introduction
I have a data structure : pool of values. (not pool of pointers)
When I called create(), it will return Handle.
Everything is good so far.
template<class T> class Pool{
std::vector<T> v; //store by value
Handle<T> create(){ .... }
}
template<class T> class Handle{
Pool<T>* pool_; //pointer back to container
int pool_index_; //where I am in the container
T* operator->() {
return pool_->v.at(pool_index_); //i.e. "pool[index]"
}
void destroy(){
pool_-> ... destroy(this) .... mark "pool_index_" as unused, etc ....
}
}
Now I want Handle<> to support polymorphism.
Question
Many experts have kindly advised me to use weak_ptr, but I still have been left in blank for a week, don't know how to do it.
The major parts that I stuck are :-
Should create() return weak_ptr, not Handle?
.... or should Handle encapsulate weak_ptr?
If create() return weak_ptr for user's program, ...
how weak_ptr would know pool_index_? It doesn't have such field.
If the user cast weak_ptr/Handle to a parent class pointer as followed, there are many issues :-
e.g.
class B{}
class C : public B { ......
}
....
{
Pool<C> cs;
Handle<C> cPtr=cs.create();
Handle<B> bPtr=cPtr; // casting ;expected to be valid,
// ... but how? (weak_ptr may solve it)
bPtr->destroy() ; // aPtr will invoke Pool<B>::destroy which is wrong!
// Pool<C>::destroy is the correct one
bPtr.operator->() ; // face the same problem as above
}
Assumption
Pool is always deleted after Handle (for simplicity).
no multi-threading
Here are similar questions, but none are close enough.
C++ object-pool that provides items as smart-pointers that are returned to pool upon deletion
C++11 memory pool design pattern?
Regarding weak_ptr
A std::weak_ptr is always associated with a std::shared_ptr. To use weak_ptr you would have to manage your objects with shared_ptr. This would mean ownership of your objects can be shared: Anybody can construct a shared_ptr from a weak_ptr and store it somewhere. The pointed-to object will only get deleted when all shared_ptr's are destroyed. The Pool will lose direct control over object deallocation and thus cannot support a public destroy() function.
With shared ownership things can get really messy.
This is one reason why std::unique_ptr often is a better alternative for object lifetime management (sadly it doesn't work with weak_ptr). Your Handle::destroy() function also implies that this is not what you want and that the Pool alone should handle the lifetime of its objects.
However, shared_ptr/weak_ptr are designed for multi-threaded applications. In a single-threaded environment you can get weak_ptr-like functionality (check for valid targets and avoid dangling pointers) without using weak_ptr at all:
template<class T> class Pool {
bool isAlive(int index) const { ... }
}
template<class T> class Handle {
explicit operator bool() const { return pool_->isAlive(pool_index_); }
}
Why does this only work in a single-threaded environment?
Consider this scenario in a multi-threaded program:
void doSomething(std::weak_ptr<Obj> weak) {
std::shared_ptr<Obj> shared = weak.lock();
if(shared) {
// Another thread might destroy the object right here
// if we didn't have our own shared_ptr<Obj>
shared->doIt(); // And this would crash
}
}
In the above case, we have to make sure that the pointed-to object is still accessible after the if(). We therefore construct a shared_ptr that will keep it alive - no matter what.
In a single-threaded program you don't have to worry about that:
void doSomething(Handle<Obj> handle) {
if(handle) {
// No other threads can interfere
handle->doIt();
}
}
You still have to be careful when dereferencing the handle multiple times. Example:
void doDamage(Handle<GameUnit> source, Handle<GameUnit> target) {
if(source && target) {
source->invokeAction(target);
// What if 'target' reflects some damage back and kills 'source'?
source->payMana(); // Segfault
}
}
But with another if(source) you can now easily check if the handle is still valid!
Casting Handles
So, the template argument T as in Handle<T> doesn't necessarily match the type of the pool. Maybe you could resolve this with template magic. I can only come up with a solution that uses dynamic dispatch (virtual method calls):
struct PoolBase {
virtual void destroy(int index) = 0;
virtual void* get(int index) = 0;
virtual bool isAlive(int index) const = 0;
};
template<class T> struct Pool : public PoolBase {
Handle<T> create() { return Handle<T>(this, nextIndex); }
void destroy(int index) override { ... }
void* get(int index) override { ... }
bool isAlive(int index) const override { ... }
};
template<class T> struct Handle {
PoolBase* pool_;
int pool_index_;
Handle(PoolBase* pool, int index) : pool_(pool), pool_index_(index) {}
// Conversion Constructor
template<class D> Handle(const Handle<D>& orig) {
T* Cannot_cast_Handle = (D*)nullptr;
(void)Cannot_cast_Handle;
pool_ = orig.pool_;
pool_index_ = orig.pool_index_;
}
explicit operator bool() const { return pool_->isAlive(pool_index_); }
T* operator->() { return static_cast<T*>( pool_->get(pool_index_) ); }
void destroy() { pool_->destroy(pool_index_); }
};
Usage:
Pool<Impl> pool;
Handle<Impl> impl = pool.create();
// Conversions
Handle<Base> base = impl; // Works
Handle<Impl> impl2 = base; // Compile error - which is expected
The lines that check for valid conversions are likely to be optimized out. The check will still happen at compile-time! Trying an invalid conversion will give you an error like this:
error: invalid conversion from 'Base*' to 'Impl*' [-fpermissive]
T* Cannot_cast_Handle = (D*)nullptr;
I uploaded a simple, compilable test case here: http://ideone.com/xeEdj5
I have a function that given a path name, does a look up and returns a pointer to the associated value. Sometimes the value lives in a static cache, sometimes it gets calculated and created on the fly.
So, sometimes the caller takes ownership and needs to delete the object after reading it, and sometimes not. I'm wondering, is there something I can wrap this pointer with so that it will automatically be freed as necessary by the caller?
I was thinking I might be able to use a unique_ptr, but isn't the deleter part of the type, so how could I return the same type that sometimes does and sometimes doesn't actually delete.
So indeed, one solution could be returning a normal std::shared_ptr for the value created inside the function, and another one with an empty deleter for the value that lives in the map.
Live example of this solution
You can see how both use cases don't require any actions from the calling code and are completely transparent.
You can use std::unique_ptr with a deleter that knows whether to free or not. While the deleter type is part of the unique_ptr type, different unique_ptr instances can have different deleter instances:
template <class T>
class delete_if_not_cached {
bool cached;
public:
delete_if_not_cached(bool c = false) : cached(c) {}
void operator()(T *obj) { if (!cached) delete obj; }
}
and you have your function return a std::unique_ptr<T, delete_if_not_cached<T>>. If you're returning a pointer into the cache, you create that pointer as:
return std::unique_ptr<T, delete_if_not_cached<T>>(raw_pointer, delete_if_not_cached<T>(true));
to return a non-cached object, use
return std::unique_ptr<T, delete_if_not_cached<T>>(new T(...))
One potential pitfall is that if you ever remove things from the cache, that might leave dangling unique_ptrs that you have previously returned. If that's an issue, it probably makes more sense to use shared_ptrs both to return and in the cache itself.
You could use a std::shared_ptr but that does not really describe your ownership model. Have you considered rolling your own wrapper that contains a std::unique_ptr and a raw pointer and uses the correct one depending on the circumstances? Something like:
#include <cassert>
#include <memory>
class MyClass { };
class Wrapper {
const MyClass* cached_;
std::unique_ptr<MyClass> owned_;
public:
Wrapper() : cached_(nullptr) {}
void setCached(const MyClass* cached) {cached_ = cached;}
void setOwned(std::unique_ptr<MyClass> owned) { owned_ = std::move(owned); }
const MyClass* get() const {return cached_ ? cached_ : owned_.get();}
};
Wrapper getWrapper(int i) {
static MyClass first;
static MyClass second;
Wrapper wrapper;
if (i == 0)
wrapper.setCached(&first);
else if (i == 1)
wrapper.setCached(&second);
else
wrapper.setOwned(std::unique_ptr<MyClass>(new MyClass()));
return wrapper;
}
int main() {
for (int i = 0; i != 4; ++i) {
Wrapper wrapper = getWrapper(i);
assert(wrapper.get() != nullptr);
}
}
The wrapper can either forward calls to the real class or provide access to a raw pointer to the real class.
Or the wrapper could work polymorphically, with an interface and two implementations. One with a raw pointer and one with a unique pointer:
#include <cassert>
#include <memory>
class MyClass {};
class Wrapper {
public:
virtual ~Wrapper() = 0;
virtual const MyClass* get() const = 0;
};
Wrapper::~Wrapper() {}
class OwnerWrapper : public Wrapper {
std::unique_ptr<MyClass> owned_;
public:
OwnerWrapper(std::unique_ptr<MyClass> in) : owned_(std::move(in)) {}
virtual const MyClass* get() const { return owned_.get(); }
};
class PtrWrapper : public Wrapper {
const MyClass* ptr_;
public:
PtrWrapper(const MyClass* ptr) : ptr_(ptr) {}
virtual const MyClass* get() const { return ptr_; }
};
std::unique_ptr<Wrapper> getWrapper(int i) {
static MyClass first;
static MyClass second;
if (i == 0)
return std::unique_ptr<Wrapper>(new PtrWrapper(&first));
else if (i == 1)
return std::unique_ptr<Wrapper>(new PtrWrapper(&second));
else {
std::unique_ptr<MyClass> myclass(new MyClass());
return std::unique_ptr<Wrapper>(new OwnerWrapper(std::move(myclass)));
}
}
int main() {
for (int i = 0; i != 4; ++i) {
auto wrapper = getWrapper(i);
assert(wrapper->get() != nullptr);
}
}
I need a way to instantiate objects based on its class name passed by as a std::string. This is working right now, but need to be generalized:
void* create(std::string name) {
if(name == "classOne") return new ClassOne();
else if(name == "classTwo") return new ClassTwo();
/* ... */
}
What i do not have:
Control over the classes to be instantiated: could be thirty party classes. No changes may be done to this classes (i.e. base ancestor, polymorphic creator method, etc...)
Full class name listing: more classes could be added later and should not incur in changes to this factory.
Wrappers around the classes to be instantiated: As a result of the previous two points.
Anything else is a go.
The best use case scenario will be:
int main() {
void *obj = create("classTree"); // create object based on the string name
/* ... */
// once we know by context which specific class we are dealing with
ClassTree *ct = (ClassTree*)obj; // cast to appropiate class
std::cout << ct->getSomeText() << std::endl; // use object
}
As a side, and maybe irrelevant note, take in account the object to be instantiated may come from a class or a struct.
ADDED INFORMATION
I see more context is needed. Here is my particular use case, simplified:
// registration mechanism
int main() {
std::map< std::string, void(*func)(std::string, void*) > processors; // map of processors by class name
processors["ClassFour"] = (void(*)(std::string, void*)) &classFourMessageProcessor; // register processor (cast needed from specific to generic)
}
// function receiving string messages
void externalMessageHandler(std::string msg) {
std::string objType = extractTypeFromMessageHeader(msg); // extract type from message
// now that we know what we are dealing with, create the specific object
void *obj = create(objType); // << creator needed
processors[objType](msg, obj); // dispatch message to process
}
// previously registered message processor
void classFourMessageProcessor(std::String msg, ClassFour *obj) {
std::string streetAddress = msg.substr(10, 15); // knowing the kind of message we can extract information
obj->moveTheEtherTo(streetAddress); // use the created object
}
ADDED INFORMATION
I am using C++11 with the latest GNU compiler.
You can just store a factory function for every class type. An easy way is to use a template
template <typename T>
void* creator() {
return new T();
}
and store those in the map as well (i.e. "ClassFour" links to creator<ClassFour> and to ClassFourMessageProcessor).
Edit: for clarification, processors becomes a
typedef void* (*CreatorFunc)();
typedef void (*ProcessorFunc)(std::string, void*);
typedef std::pair<CreatorFunc, ProcessorFunc> Entry;
std::map< std::string, Entry > processors;
Adding a new class is as simple as
processors["SomeClass"] = Entry(creator<SomeClass>, ClassFourMessageProcessor);
Here's one take:
For each class, create a createInsrance() function (not a method) that instantiate an instance and return a pointer cast to void*. Note this function is not part of the class - just a plain function.
Maintain a map of string to function pointer to createInstance type function.
"Register" each of the relevant classes in the map - add the string-function pointer pair to the map.
Now the generic create will search for the string in the map and invoke the specific createInstane, returning the new instance's ptr.
Now you made no changes to the classes, and can add more classes without reprogramming the factory.
You may probably put at least #1 as a template - be sure to make the compiler instantiate the specific implementation.
maybe the following aproach with a lookup table will be a nice solution.
(Note: I don't know wich compiler are you using, so this solution is for c++03, you could take unordered_map instead map if you are using a compiler with c++11 support)
(Note 2: You could use smart pointers too, and take care of the returns values, whit this example I only wants to show an aproach)
#include <iostream>
#include <string>
#include <map>
#include <vector>
struct ClassMaker
{
virtual void* getInstance() const = 0;
virtual ~ClassMaker() {}
};
class Factory
{
private:
std::map<std::string, ClassMaker*> lookupTable;
typedef typename std::map<std::string, ClassMaker*>::iterator Iterator;
public:
void addClass(const std::string& key, ClassMaker* const newClassMaker)
{
lookupTable[key] = newClassMaker;
}
void* create(const std::string& key)
{
void* result = NULL;
Iterator it = lookupTable.find(key);
if(it != lookupTable.end())
result = (it->second)->getInstance();
return result;
}
void releaseTable()
{
for (Iterator it = lookupTable.begin(); it != lookupTable.end(); ++it)
delete it->second;
}
};
struct IntCreator : public ClassMaker
{
void* getInstance() const
{
return new int;
}
};
struct StringCreator : public ClassMaker
{
void* getInstance() const
{
return new std::string;
}
};
int main()
{
Factory myFactory;
myFactory.addClass("int", new IntCreator);
myFactory.addClass("string", new StringCreator);
int* myInt = reinterpret_cast<int*>(myFactory.create("int"));
*myInt = 10;
std::cout<< *myInt << std::endl;
delete myInt;
myFactory.releaseTable();
return 0;
}
Would you consider Boost.MPL? Unlike STL, it allows creation of containers containing types, not instances. Having a map from string to a type would give you desired factory, isn't it?
how to remove function that bound to member function of this object :
std::vector<std::function<void(int)>> callbacks;
class MyClass {
public:
MyClass() {
callbacks.push_back(
std::bind(&MyClass::myFunc,this,std::placeholders::_1)
);
}
~MyClass() {
auto it = std::remove_if( std::begin(callbacks),
std::end(callbacks),
[&](std::function<void(int)>& f) {
return // <-- this is my question
// true (remove) if f is bound to member function
// of this
});
callbacks.erase(it,std::end(callbacks));
}
void myFunc(int param){...}
};
typedef decltype(std::bind(&MyClass::myFunc,this,std::placeholders::_1)) bound_type;
auto it = std::remove_if( std::begin(callbacks),
std::end(callbacks),
[](const std::function<void(int)>& f) {
return f.target<bound_type>() != nullptr;
});
The member function template std::function::target<T> returns a pointer to the target object if it is of type T, otherwise it returns null. So you just need to be able to name the type of the target object, which you can get from decltype. Pretty simple really :-)
N.B. that will remove any callbacks of that type, not only ones that have bound the this pointer for the specific object being destroyed. If you are trying to prevent invoking callbacks on an object after it has been destroyed and have no possible way to identify which elements of the vector refer to which objects, you could consider putting a shared_ptr in your class, then storing a weak_ptr to it in the callback, which can be used to detect if the object has been destroyed:
class MyClass
{
struct NullDeleter { void operator()(void*) const { } };
std::shared_ptr<MyClass> sp;
static void safe_invoke(void (MyClass::*f)(int), const std::weak_ptr<MyClass>& wp, int i)
{
if (std::shared_ptr<MyClass> safe_this = wp.lock())
(safe_this.get()->*f)(i);
}
public:
MyClass() : sp(this, NullDeleter()) {
callbacks.push_back(
std::bind(safe_invoke, &MyClass::myFunc ,std::weak_ptr<MyClass>(sp),
std::placeholders::_1)
);
};
This wraps the call to the member function with the invoke function that converts the weak_ptr to a shared_ptr before calling the member function. If the object has been destroyed the shared_ptr will be empty, so the function does nothing. This doesn't actually remove the callback when it becomes invalid, but does make it safe to call.
You can't in the general case without a buttload of extra work. Type erasure clears this information from the object, and std::function does not expose this information directly.
Your specific example may only have one member function that could be the candidate to remove, but what about a class with 5 members that could be stored as callbacks? You'll need to test for all of them, and it's also possible to bind member functions using a lambda, which is pretty much undetectable.
Here's one solution if:
all callbacks are registered from within MyClass
the container is amended to store extra information
you're willing to do all the extra bookkeeping
std::vector<std::pair<std::function<void(int)>, void*>> callbacks;
class MyClass{
static unsigned const num_possible_callbacks = 2; // keep updated
std::array<std::type_info const*, num_possible_callbacks> _infos;
unsigned _next_info;
// adds type_info and passes through
template<class T>
T const& add_info(T const& bound){
if(_next_info == num_possible_callbacks)
throw "oh shi...!"; // something went out of sync
_infos[_next_info++] = &typeid(T);
return bound;
}
public:
MyClass() : _next_info(0){
using std::placeholders::_1;
callbacks.push_back(std::make_pair(
add_info(std::bind(&MyClass::myFunc, this, _1)),
(void*)this));
callbacks.push_back(std::make_pair(
add_info([this](int i){ return myOtherFunc(i, 0.5); }),
(void*)this));
}
~MyClass(){
using std::placeholders::_1;
callbacks.erase(std::remove_if(callbacks.begin(), callbacks.end(),
[&](std::pair<std::function<void(int)>, void*> const& p) -> bool{
if(p.second != (void*)this)
return false;
auto const& f = p.first;
for(unsigned i = 0; i < _infos.size(); ++i)
if(_infos[i] == &f.target_type())
return true;
return false;
}), callbacks.end());
}
void myFunc(int param){ /* ... */ }
void myOtherFunc(int param1, double param2){ /* ... */ }
};
Live example on Ideone.
I once needed to do something like this and I solved it by storing a vector of shared pointers of objects in the class that contain the function and remove the function from the vector by value when they are destroyed, which also makes this automatic.