My question is reasonably simple: How do I obtain a pointer to the object calling a function, without passing this?
The reason I am asking, however, is slightly more complex.
I am led to ask this because I am writing a class (named SubordnateRegistry), which contains a heterogeneous list (of lists) of function delegates --- callable objects with different signatures.
Whichever classes wish to have delegates called must register themselves, of course, with the type of data which they wish to receive, and either a pointer to the object or an already-constructed delegate. A call from inside a class Bar might look like this:
ARegistry.Subscribe <Foo> (& Bar:: BarFunction, this);
Or like this:
using namespace std:: placeholders;
auto Func = std:: bind (& Bar:: BarFunction, this, _1);
ARegistry.Subscribe <Foo> (Func);
Because std:: function is more versatile (you can bind any callable, including lambdas), I would prefer to use that over raw pointers.
My problem lies in the fact that I have to specify this all the time. If I pass an invalid pointer, or end up registering an object which is not related at all, then I will end up invoking UB at some indeterminate point in the future with no idea where it came from or where the root of the error is. Nasty!
Now, if you're wondering what happens if the caller is not an object (a free function), then the element will simply remain registered forever, as I will never automatically remove (unregister) the callable, as it never destructs.
Any ideas, or is this impossible as I was led to believe? Is preprocessor magic an option? Is there a better way?
Of course, any questions are welcome. Thanks for your time :).
You could use a #define to include this automatically, for instance.
#define REG_SUBSCRIBE(t,f) ARegistry.Subscribe <t> (f, this)
Of course that could turn ugly fast, so I don't know if I would recommend it.
If you are worried about keeping track and releasing them, then I would recommend returning an object with a destructor which unsubscribes the thing. Alternatively (or in addition) providing a method call to do that.
I gave it a shot using the curiously recurring template pattern. The idea is to encapsulate the registration of a method in a class whose destructor will automatically unregister the client object on destruction. The Client derives from this class. This way the destructor will be called automatically, and the registration class has implicit access to the clients this pointer. Such that it is not necessary to pass it explicitely.
The Visitor class
Throughout this answer I will assume the following visitor class:
// The visitor class. Clients can register methods here.
class Visitor {
public:
// Expects void(void) methods.
template <class T>
using method_t = void (T::*)();
// Register a new method of a client.
template <class T>
void subscribe(method_t<T> method, T* object);
// unsubscribe all methods of a given client.
template <class T>
void unsubscribe(T* object);
};
A registration of a method
The registration class looks like this:
// CRTP registration class.
// Will automatically subscribe and unsubscribe its base class.
template <class Derived>
class Registration {
public:
// The constructor takes a reference to the visitor,
// and a pointer to the method that should be registered.
// It will then register this particular method.
Registration(Visitor &visitor, Visitor::method_t<Derived> method)
: visitor_(visitor) {
visitor_.subscribe(method, static_cast<Derived *>(this));
}
// The destructor calls the visitors unsubscribe method unregistering
// all methods of this particular client.
virtual ~Registration() {
visitor_.unsubscribe(static_cast<Derived *>(this));
}
private:
Visitor &visitor_;
};
A client
An actual client would then look like this.
// A client using the registration class.
// Has to inherit publically, otherwise the `this` pointer cast will fail.
class Client : public Registration<Client> {
public:
Client(Visitor &visitor)
: Registration<Client>(visitor, &Client::method) {}
void method();
};
You can find an example usage here.
A few notes:
Since the registration class has non-trivial destructor, you need to consider the rule of five, and need to decide what to do about the copy-/move- constructor/assignment.
This pattern needs to be changed if you want to register multiple methods of one object. Consider this a rough sketch for how you could solve your problem. The Registration class could register methods in a publically available member function instead of the constructor. If, for some reason, you need to inherit from Registration multiple times, consider factoring out the reference to the visitor and base class chaining.
The registration could also store the method pointer, if the unsubscribe method requires that one as well.
Related
I want to have a base class which has the purpose of registering it for a callback (and de-registering in destructor), the callback is a pure virtual function. Like this.
struct autoregister {
autoregister() { callback_manager.register(this); }
~autoregister() { callback_manager.deregister(this); }
virtual void call_me()=0;
};
But this seems unreliable to me, I suspect there are several race conditions in there. 1) When the callback_manager sees the pointer, the call_me is still uncallable, and it could take an arbitrary amount of time until the object finishes construction, 2) by the time deregister is called, the derived object destructor was called, so the callbacks should not be called.
One of the things I was thinking, was to check, inside callback_manager, if the pointer's call_me is valid or not, but I can't find a standard compliant way to get the address of call_me or anything. I was thinking of comparing typeid(pointer) to typeid(autoregister*) but there might be an abstract class inbetween, making this unreliable, derived : public middle {}; middle : public autoregister {};, middle's constructor can spend an hour, e.g. loading SQL or searching google, and the callback sees that it's not the base class, and thinks the callback can be invoked, and boom. Can this be done?
Q1: are there other race conditions?
Q2: how to do this right (without race conditions, undefined behavior and other errors) without asking the derived class to call register manually?
Q3: how to check if a virtual function can be called on a pointer?
You should separate callback and registration handle. Nobody beside callback_manager needs call_me method, so why keep it visible from outside? Use std::function as a callback because it is very convenient: any callable can be converted to it and lambdas are very handy. Return a Handle object from callback registration method. The only method Handle will have would be a destructor from which you will remove the callback.
class Handle {
public:
explicit Handle(std::function<void()> deleter)
: deleter_(std::move(deleter))
{}
~Handle()
{
deleter_();
}
private:
std::function<void()> deleter_;
};
class Manager {
public:
typedef std::function<void()> Callback;
Handle subscribe(Callback callback) {
// NOTE: use mutex here if this method is accessed from multiple threads
callbacks_.push_back(std::move(callback));
auto itr = callbacks_.end() - 1;
// NOTE If Handle lifetime can exceed Manager lifetime, store handlers_ in std::shared_ptr and capture a std::weak_ptr in lambda.
return Handle([this, itr]{
// NOTE: use mutex here if this method is accessed from multiple threads
callbacks_.erase(itr);
});
}
private:
std::list<Callback> callbacks_;
};
Q1: are there other race conditions?
Callback/Handle may outlive callback_manager and will try to unsubscribe itself from deleted object. This can be fixed either by policy (always unsubscribe everything before deleting manager) or by using weak pointers.
And there is an obvious race if callback_manager is accessed from multiple threads you need to guard callbacks storage with mutexes.
Q2: how to do this right (without race conditions, undefined behavior
and other errors) without asking the derived class to call register
manually?
See above.
Q3: how to check if a virtual function can be called on a pointer?
This is not possible.
In the constructor of your autoregister, since the object has not fully been constructed yet, the 'this' pointer is dangerous to pass out to the callback_manager. I would recommend a slightly different design.
struct callback {
virtual void call_me() = 0;
}
struct autoregister {
callback*const callback_;
autoregister(callback*const _callback)
: callback_(_callback) {
callback_manager.register(callback_);
}
~autoregister() {
callback_manager.deregister(callback_);
}
};
Q1: are there other race conditions?
Maybe. Your callback_manager must be synchronized, if multiple threads may use it. But my version of autoregister itself does not have race condition.
Q2: how to do this right (without race conditions, undefined behavior and other errors) without asking the derived class to call register manually?
My code is how I think can do this right.
Q3: how to check if a virtual function can be called on a pointer?
Not necessary in my code. But in general you could keep in the class a flag which is set false in the initialization list and set true when ready to be called.
A race condition is when two threads are trying to do something at the same time, and the outcome depends on the precise timing. I don't think there is a race condition in this snippet because this is only accessible to the thread executing the constructor. There may however be a race condition in callback_manager, but you haven't posted the code for that so I can't tell.
There is another issue here: Objects are constructed from the base to the most derived, so at the time autoregister's constructor is running, the virtual call_me cannot be called. See this FAQ entry. There is no way to check if a virtual function call will work apart from ensuring the class is fully constructed.
Any solution to this problem that works by inheritance can't ensure that the class being registered is fully constructed before the callback is registered, so the registration must be done externally to the class being registered. The best you can do is have some RAII wrapper which registers the object on construction and deregisters it on destruction, and perhaps force the objects to be created through a factory that handles registration.
I think #Donghui Zhang is on the right track, but still not really quite there yet, so to speak. Unfortunately, what he's done introduces its own set of pitfalls--for example, if you pass the address of a local object to autoregister's ctor, you can still register a callback object that immediately goes out of scope (but doesn't necessarily immediately get deregistered).
I also think it's questionable (at best) to define a callback interface using call_me as the member function to invoke when calling back. If you need to define a type that can be invoked like a function, C++ already defines a name for that function: operator(). I'm going to enforce that instead of call_me being present.
To do all this, I think you really want to use a template instead of inheritance:
template <class T>
class autoregister {
T t;
public:
template <class...Args>
autoregister(Args && ... args) : t(std::forward(args)...) {
static_assert(std::is_callable<T>::value, "Error: callback must be callable");
callback_manager.register(t);
}
~autoregister() { callback_manager.deregister(t); }
};
You'd use this something like this:
class f {
public:
virtual void operator()() { /* ... */ }
};
autoregister<f> a;
The static_assert assures that the type you pass as the template parameter can be called like a function.
This also supports passing arguments through autoregister to the constructor for the object it contains, so you might have something like:
class F {
public:
F(int a, int b) { ... }
void operator()() {}
};
autoregister<F> f(1,2);
...and the 1, 2 will be passed through from autoregister to F when it's constructed. Also note that this doesn't attempt to enforce a specific signature for the callback function. If you were, for example, to modify your callback manager to do the callback as int r = callback(1);, then the code would only compile if the callback objects you registered could be invoked with an int argument, and returned an int (or something that could be implicitly converted to an int, anyway). The compiler will enforce the callback having a signature compatible with how it's called. The only big shortcoming here is that if you pass a type that can be called, but (for example) can't be called with the parameter(s) that the callback manager tries to pass, the error message(s) you get may not be as readable as you'd like.
What I'm doing
I'm working on an event system. Basically there are "slots" which any member can chime into. All they need is an event name which it will be listening to, and a function. Since all the slots are stored I had to store them as a variable in a class.
The Problem
The function becomes unavailable when it's placed into the SlotBase class. I am wondering if there is a way to retain the function in the Slot class while storing in in the SlotBase class.
The Code
class SlotBase { };
// TC - Template Class
// TA - Template Arguments (types)
template <class TC, typename ...TA>
class Slot : public SlotBase {
public:
Slot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func);
}
template <int ...Is>
void SetSlot(TC* funcClass, void(TC::*func)(TA...), int_sequence<Is...>) {
function = std::bind(func, funcClass, placeholder_temp<Is>{}...);
}
void SetSlot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func, make_int_sequence<sizeof...(TA)>{});
}
std::function<void(TA...)> returnFunction(){
return function;
}
private:
std::function<void(TA...)> function;
};
//...
class RandomClass {
public:
void randomFunction(int a, float b, int c){ //do stuff };
}
//...
RandomClass randC;
SlotBase baseS;
Slot newSlot(&randC, &RandomClass::randomFunction);
baseS = newSlot;
//...
//Later on down the line when an event was found matching slot call slot function
baseS.returnFunction()(//Correct arguments go here - leaving this out (a lot more code));
I didn't include the code for the integer sequences in the 'std::bind' as it isn't related to the problem.
What I have tried
I know that if I use a Slot cast on the baseS variable that would give me the result but I am unable to do so because I don't know the templates that Slot will have.
I have seen many similar posts stating to make baseS a pointer (such as here) but I still don't understand how you would grab the function.
I think you need to start to accept that at some point if you want to use polymorph objects, you will need to create a virtual function in SlotBase. If you want to cast back to your type at creation before using the function, the polymorphism makes no sense, because you have carried the original type somewhere along with you to be able to do so, so why upcast anyway in the first time ?
If you really need to upcast, then you need to think about a RUNTIME solution to get back to access the derived functionality. In this case, this would mean you need to create a generic interface to your signals, so try to make a pure virtual method in SlotBase that will pack an undefined number of arguments, and implement that generic caller in your Slot so that it unpacks the arguments in order and calls your slot with the arguments. I don't know if variadic methods can be overriden though, that seems dubious. Otherwise you'll have to use boost::any or something to pack the arguments in a runtime collection.
I have a framework function which expects an object and a member function pointer (callback), like this:
do_some_work(Object* optr, void (Object::*fptr)()); // will call (optr->*fptr)()
How can I pass a lambda expression to it? Want to do somethink like this:
class MyObject : public Object
{
void mystuff()
{
do_some_work(this, [](){ /* this lambda I want to pass */ });
}
};
The meaning of it all is to not clutter the interface of MyObject class with callbacks.
UPD
I can improve do_some_work in no way because I don't control framework and because actually it isn't one function, there're hundreds of them. Whole framework is based on callbacks of that type. Common usage example without lambdas:
typedef void (Object::*Callback)();
class MyObject : public Object
{
void mystuff()
{
do_some_work(this, (Callback)(MyClass::do_work));
}
void do_work()
{
// here the work is done
}
};
SOLUTION Here's my solution based on Marcelo's answer:
class CallbackWrapper : public Object
{
fptr fptr_;
public:
CallbackWrapper(void (*fptr)()) : fptr_(fptr) { }
void execute()
{
*fptr_();
}
};
class MyObject : public Object
{
void mystuff()
{
CallbackWrapper* do_work = new CallbackWrapper([]()
{
/* this lambda is passed */
});
do_some_work(do_work, (Callback)(CallbackWrapper::execute));
}
};
Since we create the CallbackWrapper we can control it's lifetime for the cases where the callback is used asynchonously. Thanks to all.
This is impossible. The construct (optr->*fptr)() requires that fptr be a pointer-to-member. If do_some_work is under your control, change it to take something that's compatible with a lambda function, such as std::function<void()> or a parameterised type. If it's a legacy framework that isn't under your control, you may be able to wrap it, if it's a function template, e.g.:
template <typename Object>
do_some_work(Object* optr, void (Object::*fptr)());
Then, you can implement a wrapper template:
template <typename F>
void do_some_work(F f) {
struct S {
F f;
S(F f) : f(f) { }
void call() { f(); delete this; }
};
S* lamf = new S(f);
do_some_work(lamf, &S::call);
}
class MyObject // You probably don't need this class anymore.
{
void mystuff()
{
do_some_work([](){ /* Do your thing... */ });
}
};
Edit: If do_some_work completes asynchronously, you must allocate lamf on the heap. I've amended the above code accordingly, just to be on the safe side. Thanks to #David Rodriguez for pointing this out.
There are deeper problems with the approach that you are trying to take than the syntactical mismatch. As DeadMG suggests, the best solution is to improve the interface of do_some_work to take a functor of some sort (std::function<void()> in C++11 or with boost, or even a generic F on which operator() is called.
The solution provided by Marcelo solves the syntactical mismatch, but because the library takes the first element by pointer, it is the responsibility of the caller to ensure that the object will be alive when the callback is executed. Assuming that the callback is asynchronous, the problem with his solution (and other similar alternatives) is that the object can potentially be destroyed before the callback is executed, causing undefined behavior.
I would suggest that you use some form of plimp idiom, where the goal in this case would be to hide the need for callbacks (because the rest of the implementation might not need to be hidden you could use just another class to handle the callbacks but store it by value, if you don't want do have to dynamically allocate more memory):
class MyClass;
class MyClassCallbacks {
MyClass* ptr;
public:
MyClassCallbacks( MyClass* ptr ) : ptr(ptr) {}
// callbacks that execute code on `ptr`
void callback1() {
// do some operations
// update *ptr
}
};
class MyClass {
MyClassCallbacks callbackHandler;
public:
void mystuff() {
do_some_work( &callbackHandler, &MyClassHandler::callback1 );
}
};
In this design, the two classes are separated but represent a unique single entity, so it is fine to add a friend declaration and let MyClassCallbacks access the internal data in MyClass (both of them are one single entity, divided only to provide a cleaner interface, but coupling is already high, so adding the extra coupling requiered by friend is no problem).
Because there is a 1-1 relationship between MyClass and MyClassCallbacks instances, their lifetimes are bound and there would be no lifetime issues, except during destruction. During destruction you must ensure that there is no callback registered that can kick in while the MyClass object is being destroyed.
Since you are at it, you might want to walk the extra mile and do a proper pimpl: move all of the data and implementation into a different type that is held by pointer, and offer a MyClass that stores a pointer and offers just the public functions, implemented as forwarders to the pimpl object. This could be somehow tricky as you are using inheritance, and the pimpl idiom is a bit cumbersome to implement on type hierarchies (if you need to extend MyClass, deriving from Object could be done in the pimpl object, rather than the interface type).
I don't think you can do that. Your do_some_work() is declared to accept pointer to methods of class Object, so such should be provided. Otherwise optr->*fptr is invalid since the lambda is not member of Object. Probably you should try using std::function and adding the needed members of Object in its closure.
You must use std::function<void()>. Both function and member function pointers are highly unsuited to being callbacks.
Is there some way to allocate memory depending on the type of pointer passed?
Here is my problem: I have a 'bouncyball' and 'hero' class both inheriting from 'Actor'. To add a bouncyball, I call:
_actors.push_back(new Bouncyball());
For a hero, it would be:
_actors.push_back(new Hero());
Since _actors is a vector of Actor pointers, it works because of polymorphism. But I want to write a generic method to add new actors to my scene:
unsigned Scene::addActor(Actor * actor){
this->_actors.push_back(new [something]);
}
Because the parameter can be any derivative of Actor, I don't know what to allocate memory for... I can work around this with a case statement, but what if I derive other Actors later on?
What is wrong with this:
unsigned Scene::addActor(Actor * actor){
this->_actors.push_back(actor);
//what do you want to return? why not make return type as void?
}
Isn't it actor which you want to add to _actors?
And you can call addActor() as:
scene.addActor(new Bouncyball());
scene.addActor(new Hero());
Make sure that you declare the destructor of Actor as virtual, as most likely you would want to delete derived class objects through the pointer of base type (which is Actor).
Nawaz's solution is fine, but an alternative is a template member function:
template<typename T>
unsigned Scene::addActor()
{
_actors.push_back(new T());
}
And then in the client code:
scene.addActor<Hero>();
It's worth noting that the template member function will need to be implemented in a header or file included by a header (such as a .inl). If you implement it directly in the class body you shouldn't write Scene:: in front of addActor().
One advantage of this method is that clients are not calling new. It's generally 'bad' if code is calling new, but isn't calling delete, and in this case delete would presumably be called by the Scene class later. This also creates a pinch point if a custom allocator needs to be used for performance reasons.
Why not create a pv class Clonable:
template <typename T>
struct Clonable {
virtual smart_ptr<T> clone() const = 0;
}
for smart_ptr being std::shared_ptr, std::unique_ptr, boost::shared_ptr, etc.
The point is to refcount the pointer to avoid use of manual deletes, except when writing a custom Deleter.
Then define Actor as:
class Actor : ..., public Clonable<Actor> {
...
public:
...
virtual smart_ptr<T> clone() const { return 0; }
...
...
}
Then, for T : public Actor,
scene.addActor((T()).clone());
I've been programming in Java way too long, and finding my way back to some C++. I want to write some code that given a class (either a type_info, or its name in a string) can create an instance of that class. For simplicity, let's assume it only needs to call the default constructor. Is this even possible in C++, and if not is it coming in a future TR?
I have found a way to do this, but I'm hoping there is something more "dynamic". For the classes I expect to wish to instantiate (this is a problem in itself, as I want to leave that decision up to configuration), I have created a singleton factory with a statically-created instance that registers itself with another class. eg. for the class Foo, there is also a FooFactory that has a static FooFactory instance, so that at program startup the FooFactory constructor gets called, which registers itself with another class. Then, when I wish to create a Foo at runtime, I find the FooFactory and call it to create the Foo instance. Is there anything better for doing this in C++? I'm guessing I've just been spoiled by rich reflection in Java/C#.
For context, I'm trying to apply some of the IOC container concepts I've become so used to in the Java world to C++, and hoping I can make it as dynamic as possible, without needing to add a Factory class for every other class in my application.
You could always use templates, though I'm not sure that this is what your looking for:
template <typename T>
T
instantiate ()
{
return T ();
}
Or on a class:
template <typename T>
class MyClass
{
...
};
Welcome in C++ :)
You are correct that you will need a Factory to create those objects, however you might not need one Factory per file.
The typical way of going at it is having all instanciable classes derive from a common base class, that we will call Base, so that you'll need a single Factory which will serve a std::unique_ptr<Base> to you each time.
There are 2 ways to implement the Factory:
You can use the Prototype pattern, and register an instance of the class to create, on which a clone function will be called.
You can register a pointer to function or a functor (or std::function<Base*()> in C++0x)
Of course the difficulty is to register those entries dynamically. This is typically done at start-up during static initialization.
// OO-way
class Derived: public Base
{
public:
virtual Derived* clone() const { return new Derived(*this); }
private:
};
// start-up...
namespace { Base* derived = GetFactory().register("Derived", new Derived); }
// ...or in main
int main(int argc, char* argv[])
{
GetFactory().register("Derived", new Derived(argv[1]));
}
// Pointer to function
class Derived: public Base {};
// C++03
namespace {
Base* makeDerived() { return new Derived; }
Base* derived = GetFactory().register("Derived", makeDerived);
}
// C++0x
namespace {
Base* derived = GetFactory().register("Derived", []() { return new Derived; });
}
The main advantage of the start-up way is that you can perfectly define your Derived class in its own file, tuck the registration there, and no other file is impacted by your changes. This is great for handling dependencies.
On the other hand, if the prototype you wish to create requires some external information / parameters, then you are forced to use an initialization method, the simplest of which being to register your instance in main (or equivalent) once you have the necessary parameters.
Quick note: the pointer to function method is the most economic (in memory) and the fastest (in execution), but the syntax is weird...
Regarding the follow-up questions.
Yes it is possible to pass a type to a function, though perhaps not directly:
if the type in question is known at compile time, you can use the templates, though you'll need some time to get acquainted with the syntax
if not, then you'll need to pass some kind of ID and use the factory approach
If you need to pass something akin to object.class then it seems to me that you are approaching the double dispatch use case and it would be worth looking at the Visitor pattern.
No. There is no way to get from a type's name to the actual type; rich reflection is pretty cool, but there's almost always a better way.
no such thing as "var" or "dynamic" in C++ last time I've checked(although that was a WHILE ago). You could use a (void*) pointer and then try casting accordingly. Also, if memory serves me right, C++ does have RTTI which is not reflection but can help with identifying types at runtime.