I am just thinking about a way to check an object to be valid in a automated way.
I have a couple of hardware related objects (like class A), which can be deleted by external (physical) events.
To detect this I have used shared/weak pointer. But now I am struggling with the checking of the weak pointer. Since this is done in the same way for each member function for many objects, I am currently searching for a way to do this with less redundant code.
In addition I am writing a library and do not want the user to handle this (simply return the weak pointer to the user to handle it by himself is therefor no option)
My best guess is shown below. My problem is, I could not find a way to generate the member functions (func1, and many more ...) automatically within the template. Doing it by myself would result in lot of redundant code for every member function to be validated (and there are a lot)
Each member function of A (and many more other objects) shall be wrapped by a function doing the validation shown below. This is same for all member functions and done for many classes which can be used as type for the Validator.
Does anyone has an idea how to solve this? Maybe there are other (better) ways to solve this.
Many thanks for your help.
Some constraints:
Only C++11 possible,
No exceptions
class A {
public:
void func1() {}
//many more functions
};
template<typename T>
class Validator
{
//has to be done for all functions of A
void func1()
{
if (!wptr.expired())
{
wptr.lock()->func1();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
I would protect the full user function call:
class A {
public:
void func1() {}
//many more functions
};
template <typename T>
class Validator
{
public:
#if 1 // template way, but no-expressive signature
template <typename F>
void do_job(F f)
#else // type-erasure way, expressive, but with some overhead
void do_job(std::function<void (T&)> f)
#endif
{
auto t = wptr.lock();
if (t) {
f(*t);
} else {
errorHandling();
}
}
private:
void errorHandling();
private:
std::weak_ptr<T> wptr;
};
So user might chain call:
Validator<A> val;
val.do_job([](A& a)
{
a.func1();
a.func2();
});
If the caller can live with clunky syntax you can use member function pointers:
#include <memory>
#include <iostream>
class A {
public:
void func1() {
std::cout << "hello func1\n";
}
};
template<typename T>
class Validator
{
public:
Validator(std::shared_ptr<T> p) : wptr(p) {}
template <typename MemFun>
void call(MemFun mf) {
if (!wptr.expired())
{
(wptr.lock().get()->*mf)();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
int main() {
auto x = std::make_shared<A>();
Validator<A> v{x};
v.call(&A::func1);
}
Related
I'm reading a lot of questions (and answers) about function pointers, functors and callbacks but I still have a confusion about which is the right tool for me.
Some of them cannot apply to my scenario because it seems my compiler avr-gcc v5.4.0 does not have C++ standard library (i.e. std::function is not available).
This is my base class:
class Debouncer
{
public:
typedef uint8_t (Debouncer::*debouncer_raw_t) (void);
Debouncer() {}
void setRawFunction(Debouncer::debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw();
// do something
}
}
In my other classes I have:
class Inputs
{
public:
Inputs()
{
_deb.setRawFunction(myRaw);
}
private:
Debouncer _deb;
uint8_t myRaw()
{
return something;
}
}
Of course this won't compile because myRaw is not static.
Anyway, I'm going to try to avoid this because it would break the existing code.
If I'm not wrong, a lot of questions seem to ask the other way around.
Instead I just want to pass the pointer of my member function to my Debouncer class, so it can call _raw() when it needs to.
Here I found this advise to avoid std:: library:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
void userCode(Fred& fred, FredMemFn p) // Use a typedef for pointer-to-member types
{
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
// Would normally be: int ans = (fred.*p)('x', 3.14);
// ...
}
But it seems the other way around. Here the class Fred is my Debouncer.
I don't want to call the Debouncer member, but member of the caller class (i.e. Input::myRaw()).
Would you please help me to understand which is the right tool to achieve such a simple task?
Making a member function virtual is a relatively low-overhead way to have a single pointer (to an object) refer to both the object's data and the correct member function.
class InputsBase
{
// All classes that implement myRaw() should inherit from this class
public:
virtual uint8_t myRaw() = 0;
};
class Inputs : public InputsBase
{
public:
Inputs()
{
_deb.setRawFunction(this);
}
private:
Debouncer _deb;
virtual uint8_t myRaw()
{
return something;
}
}
Your Debouncer can then simply store a pointer to the object in question.
class Debouncer
{
public:
typedef InputsBase* debouncer_raw_t;
Debouncer() {}
void setRawFunction(debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw->myRaw();
// do something
}
}
If you know (or require) each of the classes using Debouncer have a public myRaw() function (or better operator(), or actually anything else), the problem is simpler:
template <typename T>
class Debouncer
{
public:
Debouncer (T* t): _t(t) {}
void anotherFunction()
{
uint8_t value = _t->myRaw();
std::cout << static_cast<int>(value);
}
private:
T* _t;
};
class Inputs
{
public:
Inputs() : _deb(this)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs> _deb;
};
int main()
{
Inputs i;
i.foo();
}
This would be preferred solution in C++. See for example standard library <algorithm> - any function taking a predicate or some other callable expects to call it with operator() rathen than having to deal with pointers-to-member-function.
If you don't know what function should be called and you really cannot impose any requirement on the classes, you need to store both a pointer (or reference) to the class and a pointer to the member function. Note that you cannot connect pointers to member functions of different classes, so we need templates once again:
template <typename T, typename Func>
class Debouncer
{
public:
Debouncer (T* t, Func f): _t(t), _f(f) {}
void anotherFunction()
{
uint8_t value = (_t->*_f)(); //I get it now why isocpp asks to use macro here, the syntax is horrible
std::cout << static_cast<int>(value);
}
private:
T* _t;
Func _f;
};
class Inputs
{
public:
Inputs() : _deb(this, &Inputs::myRaw)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs, decltype(&Inputs::myRaw)> _deb; //decltype is C++11, you could also declare type like you did in your question
};
int main()
{
Inputs i;
i.foo();
}
I want to implement a class hierarchy for object dispatching. Different classes dispatch different elements, and each class can dispatch its element represented as different data types.
It is better understood through a (faulty) example. This is what I would like to have if virtual function templating was allowed:
class Dispatcher {
template <class ReturnType>
virtual ReturnType getStuffAs();
};
So that I can implement subclasses as:
class CakeDispatcher : public Dispatcher {
template <>
virtual Recipe getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
};
class DonutDispatcher : public Dispatcher {
template <>
virtual Frozen getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
}
So that I can do the following later on:
void function( Dispatcher * disp ) {
// Works for Donut and Cake, but result will be a different Baked object
Baked b = disp->getStuffAs<Baked>();
// works if disp points to a DonutDispatcher
// fails if it is a CakeDispatcher
// can be compiling/linking time error or runtime error. I don't care
Frozen f = disp->getStuffAs<Frozen>();
}
Requirements/constraints:
All possible return types are not known beforehand. That's why I "need" templates.
Each class can provide just some return types.
Classes must have a common ancestor, so that I can store objects through a pointer to parent class and invoke functions through this pointer.
EDIT: I CAN'T use C++11 features, but I CAN use boost library.
Things I've thought about, but are not a solution:
Obviously, virtual template functions
Curiously Recurring Template Pattern: breaks the condition of common ancestor
Using some kind of traits class containing the functionality of children classes, but it does not work because a non-virtual implementation in the parent class does not have access to this information
I could maybe store some typeid info in the parent class, passed by children on construction. This makes possible for the non-virtual parent dispatching method to dynamic-cast itself to the children type... but it appears to be ugly as hell, and I don't know if this can cause some kind cycle-referencing problem.
class Dispatcher {
private:
typeid(?) childType;
public:
Dispatcher(typeid childT) : childType(childT) {}
// NOT VIRTUAL
template <class ReturnType>
ReturnType getStuffAs()
{
// or something equivalent to this cast, which I doubt is a correct expression
return dynamic_cast<childType *>(this)->childGetStuffAs<ReturnType>();
}
};
Then child classes would implement childGetStuffAs functions, which are not virtual too.
I've read like 5-10 related questions, but none of the provided solutions seems to fit this problem.
Can any of you come up with a better solution?
Is there a standard pattern/technique for solving this problem?
EDIT: The real problem
In the real problem, I have physical models with properties that can be represented in multiple ways: functions, matrices, probability distributions, polynomials, and some others (for example, a non-linear system can be represented as a function but not as a a matrix, while a linear system can be transformed to both).
There are also algorithms which can use those models indistinctly, but they could require specific representations for some model features. That's the reason for the "getStuffAs" function. The whole think is a bit complicated --too much to explain it here properly--, but I can guarantee that in this context the interface is well defined: input, computation and output.
My intention was to make this possible assuming that the number of possible representations is fully defined beforehand, and making it possible to transform the products to already existing types/classes that cannot be modified.
However, i'm starting to realize that this is, indeed, not possible in a simple way --I don't want to write a library just for this problem.
#include <cstdio>
// as a type identifier
struct stuff {
virtual void foo() {}
};
template <typename T>
struct stuff_inh : stuff {
};
struct Dispatcher {
template <typename T>
T* getStuffAs() {
return (T*)((getStuffAsImpl( new stuff_inh<T>() )));
}
virtual void* getStuffAsImpl(void*) = 0;
virtual void type() {printf("type::dispatcher\n");}
};
struct Cake : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("cake impl\n");
if (dynamic_cast<stuff_inh<Cake>*>(s) == NULL) {
throw "bad cast";
}
return (void*)(new Cake());
}
virtual void type() {printf("type::Cake\n");}
};
struct Rabbit : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("rabbit impl\n");
if (dynamic_cast<stuff_inh<Rabbit>*>(s) != NULL) {
return (void*)(new Rabbit());
}
else if (dynamic_cast<stuff_inh<Cake>*>(s) != NULL) {
return (void*)(new Cake());
}
else {
throw "bad cast";
}
}
virtual void type() {printf("type::Rabbit\n");}
};
void foo(Dispatcher* d) {
d->getStuffAs<Cake>()->type();
d->getStuffAs<Rabbit>()->type();
}
int main() {
Rabbit* r = new Rabbit;
foo(r);
Cake* c = new Cake;
foo(c);
}
I an not sure about the correctness of this ugly solution, may it be helpful for you. >_<
deletion of resource is not coded for a clearer look.
My solution is a combination of recurring template and diamond inheritance.
At least it's working. :)
#include <iostream>
class Dispatcher
{
public:
template<class T>
T getStuff()
{
return T();
}
};
template<class T>
class Stuffer : public Dispatcher
{
public:
template<class TT=T>
TT getStuff(){
return reinterpret_cast<TT>(this);
}
};
class Cake{
public:
Cake(){}
void print()
{
std::cout << "Cake" << std::endl;
}
};
class Recipe
{
public:
Recipe(){}
void print()
{
std::cout << "Recipe" << std::endl;
}
};
class CakeRecipe : public Stuffer<Cake>, public Stuffer< Recipe >
{
public:
};
int main()
{
Dispatcher* cr = reinterpret_cast<Dispatcher*>(new CakeRecipe());
cr->getStuff<Cake>().print();
cr->getStuff<Recipe>().print();
getchar();
return 1;
}
Templated virtual member functions are not supported in C++ but I have a scenario where it would be ideal. Im wondering if someone has ideas for ways to accomplish this.
#include <iostream>
class Foo {
public:
virtual void bar(int ){}
// make a clone of my existing data, but with a different policy
virtual Foo* cloneforDB() = 0;
};
struct DiskStorage {
static void store(int x) { std::cout << "DiskStorage:" << x << "\n"; }
};
struct DBStorage {
static void store(int x) { std::cout << "DBStorage:" << x << "\n"; }
};
template<typename Storage>
class FooImpl : public Foo {
public:
FooImpl():m_value(0) {}
template<typename DiffStorage>
FooImpl(const FooImpl<DiffStorage>& copyfrom) {
m_value = copyfrom.m_value;
}
virtual void bar(int x) {
Storage::store(m_value);
std::cout << "FooImpl::bar new value:" << x << "\n";
m_value = x;
}
virtual Foo* cloneforDB() {
FooImpl<DBStorage> * newfoo = new FooImpl<DBStorage>(*this);
return newfoo;
}
int m_value;
};
int main()
{
Foo* foo1 = new FooImpl<DiskStorage>();
foo1->bar(5);
Foo* foo2 = foo1->cloneforDB();
foo2->bar(21);
}
Now if I want to clone the Foo implmemetation, but with a different Storagepolicy, I have to explicitly spell out each such implementation:
cloneforDB()
cloneforDisk()
A template parameter would have simplified that.
Can anyone think of a cleaner way to do this?
Please focus on the idea and not the example, since its obviously a contrived example.
Usually if you want to use a virtual template method, it means that something is wrong in the design of your class hierarchy. The high level reason for that follows.
Template parameters must be known at compile-time, that's their semantics. They are used to guarantee soundness properties of your code.
Virtual functions are used for polymorphism, ie. dynamic dispatching at runtime.
So you cannot mix static properties with runtime dispatching, it does not make sense if you look at the big picture.
Here, the fact that you store something somewhere should not be part of the type of your method, since it's just a behavioral trait, it could change at runtime. So it's wrong to include that information in the type of the method.
That's why C++ does not allow that: you have to rely on polymorphism to achieve such a behavior.
One easy way to go would be to pass a pointer to a Storage object as an argument (a singleton if you just want one object for each class), and work with that pointer in the virtual function.
That way, your type signature does not depend on the specific behavior of your method. And you can change your storage (in this example) policy at runtime, which is really what you should ask for as a good practice.
Sometimes, behavior can be dictated by template parameters (Alexandrescu's policy template parameters for example), but it is at type-level, not method level.
Just use templates all the way:
class Foo {
public:
virtual void bar(int ){}
template <class TargetType>
Foo* clonefor() const;
};
class FooImpl { ... };
template
inline <class TargetType>
Foo* Foo::clonefor() const
{
return new FooImpl<TargetType>(*this);
}
Now call it:
int main()
{
Foo* foo1 = new FooImpl<DiskStorage>();
foo1->bar(5);
Foo* foo2 = foo1->clonefor<DBStorage>();
foo2->bar(21);
}
A trick I have sometimes used to get around this issue is this:
template<typename T>
using retval = std::vector<T const*>;
struct Bob {};
// template type interface in Base:
struct Base {
template<typename T>
retval<T> DoStuff();
virtual ~Base() {};
// Virtual dispatch so children can implement it:
protected:
virtual retval<int> DoIntStuff() = 0;
virtual retval<double> DoDoubleStuff() = 0;
virtual retval<char> DoCharStuff() = 0;
virtual retval<Bob> DoBobStuff() = 0;
};
// forward template interface through the virtual dispatch functions:
template<> retval<int> Base::DoStuff<int>() { return DoIntStuff(); }
template<> retval<double> Base::DoStuff<double>() { return DoDoubleStuff(); }
template<> retval<char> Base::DoStuff<char>() { return DoCharStuff(); }
template<> retval<Bob> Base::DoStuff<Bob>() { return DoBobStuff(); }
// CRTP helper so the virtual functions are implemented in a template:
template<typename Child>
struct BaseHelper: public Base {
private:
// In a real project, ensuring that Child is a child type of Base should be done
// at compile time:
Child* self() { return static_cast<Child*>(this); }
Child const* self() const { return static_cast<Child const*>(this); }
public:
virtual retval<int> DoIntStuff() override final { self()->DoStuff<int>(); }
virtual retval<double> DoDoubleStuff() override final { self()->DoStuff<double>(); }
virtual retval<char> DoCharStuff() override final { self()->DoStuff<char>(); }
virtual retval<Bob> DoBobStuff() override final { self()->DoStuff<Bob>(); }
};
// Warning: if the T in BaseHelper<T> doesn't have a DoStuff, infinite
// recursion results. Code and be written to catch this at compile time,
// and I would if this where a real project.
struct FinalBase: BaseHelper<FinalBase> {
template<typename T>
retval<T> DoStuff() {
retval<T> ret;
return ret;
}
};
where I go from template-based dispatch, to virtual function dispatch, back to template based dispatch.
The interface is templated on the type I want to dispatch on. A finite set of such types are forwarded through a virtual dispatch system, then redispatched at compile time to a single method in the implementation.
I will admit this is annoying, and being able to say "I want this template to be virtual, but only with the following types" would be nice.
The reason why this is useful is that it lets you write type-agnostic template glue code that operates on these methods uniformly without having to do stuff like pass through pointers to methods or the like, or write up type-trait bundles that extract which method to call.
I have a class hierarchy where I want to introduce a method template that would behave like if it was virtual. For example a simple hierarchy:
class A {
virtual ~A() {}
template<typename T>
void method(T &t) {}
};
class B : public A {
template<typename T>
void method(T &t) {}
};
Then I create object B:
A *a = new B();
I know I can get the type stored in a by typeid(a). How can I call the correct B::method dynamically when I know the type? I could probably have a condition like:
if(typeid(*a)==typeid(B))
static_cast<B*>(a)->method(params);
But I would like to avoid having conditions like that. I was thinking about creating a std::map with typeid as a key, but what would I put as a value?
You can use the "Curiously Recurring Template Pattern"
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Using this pattern, the base class takes the derived class type as a template parameter, meaning that the base class can cast itself to the derived type in order to call functions in the derived class. It's a sort of compile time implementation of virtual functions, with the added benefit of not having to do a virtual function call.
template<typename DERIVED_TYPE>
class A {
public:
virtual ~A() {}
template<typename T>
void method(T &t) { static_cast<DERIVED_TYPE &>(*this).methodImpl<T>(t); }
};
class B : public A<B>
{
friend class A<B>;
public:
virtual ~B() {}
private:
template<typename T>
void methodImpl(T &t) {}
};
It can then be used like this...
int one = 1;
A<B> *a = new B();
a->method(one);
Is there any common code you could extract and make virtual?
class A {
virtual ~A() {}
template<typename T>
void method(T &t)
{
...
DoSomeWork();
...
}
virtual void DoSomeWork() {}
};
class B : public A {
virtual void DoSomeWork() {}
};
As you may know, you cannot have templates for virtual functions, since the entirety of the virtual functions is part of the class type and must be known in advance. That rules out any simple "arbitrary overriding".
If it's an option, you could make the template parameter part of the class:
template <typename T> class A
{
protected:
virtual void method(T &);
};
template <typename T> class B : public A<T>
{
virtual void method(T &); // overrides
};
A more involved approach might use some dispatcher object:
struct BaseDispatcher
{
virtual ~BaseDispatcher() { }
template <typename T> void call(T & t) { dynamic_cast<void*>(this)->method(t); }
};
struct ConcreteDispatcher : BaseDispatcher
{
template <typename T> void method(T &);
};
class A
{
public:
explicit A(BaseDispatcher * p = 0) : p_disp(p == 0 ? new BaseDispatcher : p) { }
virtual ~A() { delete p_disp; };
private:
BaseDispatcher * p_disp;
template <typename T> void method(T & t) { p_disp->call(t); }
};
class B : public A
{
public:
B() : A(new ConcreteDispatcher) { }
// ...
};
Oops. Initially answered at the wrong question - ah well, at another question
After some thinking I recognized this as the classic multi-method requirement, i.e. a method that dispatches based on the runtime type of more than one parameter. Usual virtual functions are single dispatch in comparison (and they dispatch on the type of this only).
Refer to the following:
Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
Chapter 11: "Multimethods" - it implements basic multi-methods, making them logarithmic (using ordered typelists) and then going all the way to constant-time multi-methods. Quite powerful stuff !
A codeproject article that seems to have just such an implementation:
no use of type casts of any kind (dynamic, static, reinterpret, const or C-style)
no use of RTTI;
no use of preprocessor;
strong type safety;
separate compilation;
constant time of multimethod execution;
no dynamic memory allocation (via new or malloc) during multimethod call;
no use of nonstandard libraries;
only standard C++ features is used.
C++ Open Method Compiler, Peter Pirkelbauer, Yuriy Solodkyy, and Bjarne Stroustrup
The Loki Library has A MultipleDispatcher
Wikipedia has quite a nice simple write-up with examples on Multiple Dispatch in C++.
Here is the 'simple' approach from the wikipedia article for reference (the less simple approach scales better for larger number of derived types):
// Example using run time type comparison via dynamic_cast
struct Thing {
virtual void collideWith(Thing& other) = 0;
}
struct Asteroid : Thing {
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
}
struct Spaceship : Thing {
void collideWith(Thing& other) {
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Spaceship-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Spaceship-Spaceship collision
} else {
// default collision handling here
}
}
}
I think the only solution is the http://en.wikipedia.org/wiki/Visitor_pattern
See this topic:
How to achieve "virtual template function" in C++
Is there some library that allows me to easily and conveniently create Object-Oriented callbacks in c++?
the language Eiffel for example has the concept of "agents" which more or less work like this:
class Foo{
public:
Bar* bar;
Foo(){
bar = new Bar();
bar->publisher.extend(agent say(?,"Hi from Foo!", ?));
bar->invokeCallback();
}
say(string strA, string strB, int number){
print(strA + " " + strB + " " + number.out);
}
}
class Bar{
public:
ActionSequence<string, int> publisher;
Bar(){}
invokeCallback(){
publisher.call("Hi from Bar!", 3);
}
}
output will be:
Hi from Bar! 3 Hi from Foo!
So - the agent allows to to capsule a memberfunction into an object, give it along some predefined calling parameters (Hi from Foo), specify the open parameters (?), and pass it to some other object which can then invoke it later.
Since c++ doesn't allow to create function pointers on non-static member functions, it seems not that trivial to implement something as easy to use in c++. i found some articles with google on object oriented callbacks in c++, however, actually i'm looking for some library or header files i simply can import which allow me to use some similarily elegant syntax.
Anyone has some tips for me?
Thanks!
The most OO way to use Callbacks in C++ is to call a function of an interface and then pass an implementation of that interface.
#include <iostream>
class Interface
{
public:
virtual void callback() = 0;
};
class Impl : public Interface
{
public:
virtual void callback() { std::cout << "Hi from Impl\n"; }
};
class User
{
public:
User(Interface& newCallback) : myCallback(newCallback) { }
void DoSomething() { myCallback.callback(); }
private:
Interface& myCallback;
};
int main()
{
Impl cb;
User user(cb);
user.DoSomething();
}
People typically use one of several patterns:
Inheritance. That is, you define an abstract class which contains the callback. Then you take a pointer/reference to it. That means that anyone can inherit and provide this callback.
class Foo {
virtual void MyCallback(...) = 0;
virtual ~Foo();
};
class Base {
std::auto_ptr<Foo> ptr;
void something(...) {
ptr->MyCallback(...);
}
Base& SetCallback(Foo* newfoo) { ptr = newfoo; return *this; }
Foo* GetCallback() { return ptr; }
};
Inheritance again. That is, your root class is abstract, and the user inherits from it and defines the callbacks, rather than having a concrete class and dedicated callback objects.
class Foo {
virtual void MyCallback(...) = 0;
...
};
class RealFoo : Foo {
virtual void MyCallback(...) { ... }
};
Even more inheritance- static. This way, you can use templates to change the behaviour of an object. It's similar to the second option but works at compile time instead of at run time, which can yield various benefits and downsides, depending on the context.
template<typename T> class Foo {
void MyCallback(...) {
T::MyCallback(...);
}
};
class RealFoo : Foo<RealFoo> {
void MyCallback(...) {
...
}
};
You can take and use member function pointers or regular function pointers
class Foo {
void (*callback)(...);
void something(...) { callback(...); }
Foo& SetCallback( void(*newcallback)(...) ) { callback = newcallback; return *this; }
void (*)(...) GetCallback() { return callback; }
};
There are function objects- they overload operator(). You will want to use or write a functional wrapper- currently provided in std::/boost:: function, but I'll also demonstrate a simple one here. It's similar to the first concept, but hides the implementation and accepts a vast array of other solutions. I personally normally use this as my callback method of choice.
class Foo {
virtual ... Call(...) = 0;
virtual ~Foo();
};
class Base {
std::auto_ptr<Foo> callback;
template<typename T> Base& SetCallback(T t) {
struct NewFoo : Foo {
T t;
NewFoo(T newt) : t(newt) {}
... Call(...) { return t(...); }
};
callback = new NewFoo<T>(t);
return this;
}
Foo* GetCallback() { return callback; }
void dosomething() { callback->Call(...); }
};
The right solution mainly depends on the context. If you need to expose a C-style API then function pointers is the only way to go (remember void* for user arguments). If you need to vary at runtime (for example, exposing code in a precompiled library) then static inheritance can't be used here.
Just a quick note: I hand whipped up that code, so it won't be perfect (like access modifiers for functions, etc) and may have a couple of bugs in. It's an example.
C++ allows function pointers on member objects.
See here for more details.
You can also use boost.signals or boost.signals2 (depanding if your program is multithreaded or not).
There are various libraries that let you do that. Check out boost::function.
Or try your own simple implementation:
template <typename ClassType, typename Result>
class Functor
{
typedef typename Result (ClassType::*FunctionType)();
ClassType* obj;
FunctionType fn;
public:
Functor(ClassType& object, FunctionType method): obj(&object), fn(method) {}
Result Invoke()
{
return (*obj.*fn)();
}
Result operator()()
{
return Invoke();
}
};
Usage:
class A
{
int value;
public:
A(int v): value(v) {}
int getValue() { return value; }
};
int main()
{
A a(2);
Functor<A, int> fn(a, &A::getValue);
cout << fn();
}
Joining the idea of functors - use std::tr1::function and boost::bind to build the arguments into it before registering it.
There are many possibilities in C++, the issue generally being one of syntax.
You can use pointer to functions when you don't require state, but the syntax is really horrid. This can be combined with boost::bind for an even more... interesting... syntax (*)
I correct your false assumption, it is indeed feasible to have pointer to a member function, the syntax is just so awkward you'll run away (*)
You can use Functor objects, basically a Functor is an object which overloads the () operator, for example void Functor::operator()(int a) const;, because it's an object it has state and may derive from a common interface
You can simply create your own hierarchy, with a nicer name for the callback function if you don't want to go the operator overloading road
Finally, you can take advantage of C++0x facilities: std::function + the lambda functions are truly awesome when it comes to expressiveness.
I would appreciate a review on lambda syntax ;)
Foo foo;
std::function<void(std::string const&,int)> func =
[&foo](std::string const& s, int i) {
return foo.say(s,"Hi from Foo",i);
};
func("Hi from Bar", 2);
func("Hi from FooBar", 3);
Of course, func is only viable while foo is viable (scope issue), you could copy foo using [=foo] to indicate pass by value instead of pass by reference.
(*) Mandatory Tutorial on Function Pointers