First a disclaimer, I am replacing a bunch of code which uses boost::function and boost::bind. However, I am moving to a codebase which does not allow rtti. I would like to keep using boost but don't know if there is a way around this restriction.
So, I am trying to mimic some of its functionality, but much more simplified. I have a Callback class:
template <class Class, typename ReturnType = void> class Callback0 {
typedef ReturnType (Class::*Method)();
public:
Callback0(Class* object, Method method)
: m_object(object)
, m_method(method)
{
;
}
Callback0(const Callback0& callback)
: m_object(callback.m_object)
, m_method(callback.m_method)
{
;
}
operator bool() {
return m_object != 0;
}
operator bool() const {
return m_object != 0;
}
ReturnType operator()() {
return (m_object->*m_method)();
}
Callback0<Class, ReturnType>& operator=(const Callback0<Class, ReturnType>& callback) {
if(this != &callback) {
m_object = callback.m_object;
m_method = callback.m_method;
}
return *this;
}
private:
Class* m_object;
Method m_method;
};
This allows me to do simple callbacks with zero parameters:
class Meh {
public:
Meh() {;}
~Meh() {;}
void f0() {
footprint6v("%s\n", __FUNCTION__);
}
};
static void meh() {
Meh* m = new Meh;
Callback0<Meh, void> c0(m, &Meh::f0);
c0();
}
I would like to be able to assign my callback objects to zero as default parameters like so:
class Wtf {
public:
Wtf() : m_callback(0) {;}
~Wtf() {;}
void doSomething(const Callback0<Wtf, void>& callback = 0) {
m_callback = callback;
}
private:
Callback0<Wtf, void> m_callback;
};
This works when using boost::function as you can do:
class Wtf {
public:
Wtf() : m_callback(0) {;}
~Wtf() {;}
void doSomething(const boost::function<void()>& callback = 0) {
m_callback = callback;
}
private:
boost::function<void()> m_callback;
};
I imagine boost is doing some magic here. I know I can just change the parameter to a pointer rather than a reference but as I said, I am replacing a lot of code and would like to minimize the impact of changing from boost.
Boost isn't doing anything magic. 0 is just a NULL function pointer for the function pointer constructor.
I would suggest in your case you just provide a default constructor
Callback0() : m_object(NULL), m_method(NULL) {}
And make doSomething look like
void doSomething(const Callback0<Wtf, void>& callback = Callback0<Wtf, void>()) {
Related
I'm trying to implement a Property system in my project similar to Property system in Qt. We just started with some ideas and are in prototyping stage.
Basically, what I understood from Qt is, client should be able to pass the get function, set function and property type through some macro in the .h file. So I tried to mimic the same.
Following is my sample code:
Abstract getter class. This type of getter class is a member in Property Class
class AbstractFunc
{
public:
template < typename R >
R Invoke ()
{
return (this)->Invoke ();
}
};
Get Function template: Return values can be T , T&, const T& , T* etc..
template < typename R, class T > class GetterFunction : public AbstractFunc
{
typedef R (T::*GetterFunc) ();
public:
GetterFunction (T * obj, GetterFunc func):m_Obj (obj), m_Func (func)
{
}
R Invoke ()
{
return m_Obj->*(m_Func) ();
}
public:
T * m_Obj;
GetterFunc m_Func;
};
Property Class:
class Property
{
public:
Property (string name, AbstractFunc* getter):m_name (name), m_getter (getter)
{
}
template < typename R > R GetValue ()
{
return m_getter->Invoke < R > ();
}
private:
string m_name;
AbstractFunc* m_getter;
};
Some Window Class:
class Window
{
public:
};
Example window class
class CheckBox :public Window
{
public:
int GetChecked ()
{
return m_checked;
}
void SetChecked (int nChecked)
{
m_checked = nChecked;
}
void AddProperty (string name)
{
m_prop = new Property (name, new GetterFunction< int, Checked >(this, &Checked::GetChecked));
}
int m_checked;
Property *m_prop;
};
main function:
int main ()
{
CheckBox cc;
cc.AddProperty ("Hello");
cout<<"value:"<< cc.m_prop->GetValue<int>();
return 0;
}
PROBLEM:
Getter function is remembered as AbstractFunc in Property Class. I want to call 'Invoke' on AbstractFunc* instance and it should invoke the member function and return correct return type. The above code throws error at AbstractFunc::Invoke.
see live
Your AbstractFunc isn't abstract at all: its Invoke isn't virtual. So even though GetterFunction also has a method named Invoke, that method doesn't actually override AbstractFunc::Invoke; it just hides it. When you try to call Invoke through the AbstractFunc*, it calls AbstractFunc::Invoke, which goes into infinite recursion and thus produces UB.
I would follow #n.m.'s suggestion to make a class hierarchy like so:
class AbstractFunc {
// lock down construction
AbstractFunc() = default;
public:
template<typename R>
R Invoke();
template<typename R>
bool HasType() const noexcept;
virtual ~AbstractFunc() = default; // need to have SOME virtual method so that we have runtime type info; also a virtual destructor is required anyway
template<typename R>
friend class TypedFunc;
};
template<typename R>
struct TypedFunc : AbstractFunc { // the ONLY instances of AbstractFunc are also instances of specializations of TypedFunc
virtual R InvokeTyped() = 0;
};
// one kind of TypedFunc applies a getter on an object
template<typename R, typename T>
struct GetterFunc : TypedFunc<R> {
// you never see a GetterFunc in the interface anyway... don't see a need to hide these
T *obj; // have you considered std::shared_ptr?
R (T::*getter)();
GetterFunc(T *obj, R (T::*getter)()) : obj(obj), getter(getter) { }
R InvokeTyped() override { return (obj->*getter)(); }
};
template<typename R, typename T>
std::unique_ptr<GetterFunc<R, T>> MakeGetterFunc(T *obj, R (T::*getter)()) {
return std::make_unique<GetterFunc<R, T>>(obj, getter);
}
// another kind applies a functor, etc.
template<typename R, typename F>
struct FunctorFunc : TypedFunc<R> {
F func;
template<typename... G>
FunctorFunc(G&&... args) : func(std::forward<G>(args)...) { }
R InvokeTyped() override { return func(); }
};
This is already usable: if you have an AbstractFunc* or an AbstractFunc&, you can dynamic_cast it down to a TypedFunc of the expected type (e.g. TypedFunc<int>). If that succeeds (you get a nonnull pointer or there is no std::bad_cast exception), then you just call InvokeTyped without having to know what kind of GetterFunc/FunctorFunc/whatever you are actually dealing with. The functions Invoke and HasType declared in AbstractFunc are just sugar to help do this.
template<typename R>
bool AbstractFunc::HasType() const noexcept {
return dynamic_cast<TypedFunc<R> const*>(this);
}
template<typename R>
R AbstractFunc::Invoke() {
return dynamic_cast<TypedFunc<R>&>(*this).InvokeTyped();
// throws std::bad_cast if cast fails
}
Done.
class Property {
std::string name;
std::unique_ptr<AbstractFunc> getter;
public:
Property(std::string name, std::unique_ptr<AbstractFunc> getter) : name(std::move(name)), getter(std::move(getter)) { }
template<typename R>
bool HasType() const noexcept { return getter->HasType<R>(); }
template<typename R>
R GetValue() const { return getter->Invoke<R>(); }
std::string const &GetName() const noexcept { return name; }
};
struct Window {
virtual ~Window() = default;
// doesn't really make sense to add/remove these from outside...
virtual std::vector<Property> GetProperties() = 0;
};
class CheckBox : public Window {
int checked = 0;
public:
int GetChecked() /*const*/ noexcept { return checked; }
void SetChecked(int checked) noexcept { this->checked = checked; }
std::vector<Property> GetProperties() override {
std::vector<Property> ret;
ret.emplace_back("Boxes Checked", MakeGetterFunc(this, &CheckBox::GetChecked));
return ret;
}
};
int main() {
CheckBox cb;
cb.SetChecked(5);
for(auto const &prop : cb.GetProperties()) std::cout << prop.GetName() << ": " << prop.GetValue<int>() << "\n";
}
You could then add e.g. a virtual std::type_info const& GetType() const or similar to AbstractFunc if you want to be able to directly get at the type, etc.
This does not work:
struct Type {
virtual bool func(const std::string& val) const noexcept = 0;
}
// in main
optional<Type> = some_function_returning_optional_type();
and fails with a error message:
error: cannot declare field 'std::experimental::fundamentals_v1::_Optional_base<Type, false>::<anonymous union>::_M_payload' to be of abstract type 'Type'
Changing the Type to have a non-pure function works, but is not appropriate in this case, because there cannot be an instance of Type in my code, only classes which inherit from it should be able to exist.
std::optional<T> stores its value in-place - it therefore needs to know the size of T to work correctly, and T must be a concrete type that can be instantiated. You can think of std::optional<T> as:
template <typename T>
struct optional
{
std::aligned_storage_t<sizeof(T), alignof(T)> _data;
bool _set;
};
An abstract type represents an interface - polymorphism and some sort of indirection are required to work with abstract types. std::optional doesn't have any indirection by design.
Your proposal of optional will of course work but it would offend me to have to write
x.value()->do_something();
and I'd be concerned that users might do something daft:
x.value().reset(); // now what?
We can achieve polymorphism with a non-polymorphic interface by using a wrapper.
Here's one way:
#include <optional>
#include <iostream>
// the Foo interface/base class
struct Foo
{
virtual ~Foo() = default;
virtual Foo* clone() const { return new Foo(*this); }
virtual void do_something() {
std::cout << "something Fooey\n";
}
};
// a service for managing Foo and classes derived from Foo
struct FooService
{
template<class Arg>
Foo* clone(Arg&& arg)
{
using d_type = std::decay_t<Arg>;
return new d_type(std::forward<Arg>(arg));
}
template<class Arg>
Foo* clone(Foo* arg)
{
return arg->clone();
}
Foo* release(Foo*& other) noexcept
{
auto tmp = other;
other = nullptr;
return tmp;
}
};
// implement the Foo interface in terms of a pimpl
template<class Holder>
struct BasicFoo
{
decltype(auto) do_something() {
return get().do_something();
}
private:
Foo& get() noexcept { return static_cast<Holder*>(this)->get_impl(); }
Foo const& get() const noexcept { return static_cast<Holder const*>(this)->get_impl(); }
};
// a type for holding anything derived from a Foo
// can be initialised by anything Foo-like and handles copy/move correctly
struct FooHolder : BasicFoo<FooHolder>
{
template
<
class Arg,
std::enable_if_t
<
std::is_base_of_v<Foo, std::decay_t<Arg>>
>* = nullptr
>
FooHolder(Arg&& arg)
: service_()
, ptr_(service_.clone(std::forward<Arg>(arg)))
{}
FooHolder(FooHolder const& other)
: service_()
, ptr_(other.ptr_->clone())
{
}
FooHolder(FooHolder && other) noexcept
: service_()
, ptr_(service_.release(other.ptr_))
{
}
FooHolder& operator=(FooHolder const& other)
{
auto tmp = other;
std::swap(ptr_, tmp.ptr_);
return *this;
}
FooHolder& operator=(FooHolder && other) noexcept
{
auto tmp = std::move(other);
std::swap(ptr_, tmp.ptr_);
return *this;
}
~FooHolder()
{
delete ptr_;
}
Foo& get_impl() noexcept { return *ptr_; }
Foo const& get_impl() const noexcept { return *ptr_; }
FooService service_;
Foo* ptr_;
};
// now we can supply as many overrides of Foo as we like
struct Bar : Foo
{
virtual Foo* clone() const { return FooService().clone(*this); }
virtual void do_something() {
std::cout << "something Barey\n";
}
};
int main()
{
std::optional<FooHolder> opt;
// note that we're initialising cleanly
opt = Bar {};
// and we don't expose the pointer so the user can't
// destroy the pimpl accidentally
opt.value().do_something();
}
I am writing callbacks system. I would to have something like that:
void someFunction(int, int);
void otherFunction(int, bool, std::string);
CallbackFunc *callback1 = new CallbackFunc( someFunction );
CallbackFunc *callback2 = new CallbackFunc( otherFunction );
callback1-> call(2, 6);
callback1-> call(1024, 456);
callback2-> call(-33, true, "Hello world");
My classes should can call each given function: don't know parameters count and their types.
I was trying that:
class Callback {
public:
virtual void call(...) = 0;
};
class CallbackFunc: public Callback {
protected:
void (*m_proc)(...);
public:
CallbackFunc(void (*proc) (...)) {
this-> m_proc = proc;
}
void call (...) {
this-> m_proc(<arguments given to call>);
}
};
But it doesn't work. I have second idea:
template<typename ArgType>
class Arg {
protected:
ArgType va;
public:
Arg() {
}
Arg(ArgType v) {
this->va = v;
}
ArgType get() {
return this->va;
}
void operator =(ArgType v) {
this->va = v;
}
};
class Callback {
public:
virtual void call(Arg, ...) = 0;
};
class CallbackFunc: public Callback {
protected:
void (*m_proc)(Arg ...);
public:
CallbackFunc(void (*proc) (Arg ...)) {
this-> m_proc = proc;
}
void call (Arg arg...) {
va_list args;
va_start(args, arg);
this-> m_proc(args);
va_end(args);
}
};
Still errors. Is it possible to make this way? I want to make usable code - user shouldn't know if CallbackFunc uses templates. I can't use void* and boost. C++ 2011 is not supported completely by some compilers I use, so that I can't use this standard too.
I am trying to mimic a finally like effect. So i thought i should run a quick dirty test.
The idea was to use Most Important const to stop destruction and to put the finally block in a lambda. However apparently i did something wrong and its being called at the end of MyFinally(). How do i solve this problem?
#include <cassert>
template<typename T>
class D{
T fn;
public:
D(T v):fn(v){}
~D(){fn();}
};
template<typename T>
const D<T>& MyFinally(T t) { return D<T>(t); }
int d;
class A{
int a;
public:
void start(){
int a=1;
auto v = MyFinally([&]{a=2;});
try{
assert(a==1);
//do stuff
}
catch(int){
//do stuff
}
}
};
int main() {
A a;
a.start();
}
My Solution code (Note: You can not have two finally in the same block. as expect. But still kind of dirty)
#include <cassert>
template<typename T>
class D{
T fn; bool exec;
public:
D(T v):fn(v),exec(true){}
//D(D const&)=delete //VS doesnt support this yet and i didnt feel like writing virtual=0
D(D &&d):fn(move(d.fn)), exec(d.exec) {
d.exec = false;
}
~D(){if(exec) fn();}
};
template<typename T>
D<T> MyFinally(T t) { return D<T>(t); }
#define FINALLY(v) auto OnlyOneFinallyPlz = MyFinally(v)
int d;
class A{
public:
int a;
void start(){
a=1;
//auto v = MyFinally([&]{a=2;});
FINALLY([&]{a=2;});
try{
assert(a==1);
//do stuff
}
catch(int){
FINALLY([&]{a=3;}); //ok, inside another scope
try{
assert(a==1);
//do other stuff
}
catch(int){
//do other stuff
}
}
}
};
void main() {
A a;
a.start();
assert(a.a==2);
}
Funny enough, if you remove the & in MyFinally in the original code it works -_-.
// WRONG! returning a reference to a temporary that will be
// destroyed at the end of the function!
template<typename T>
const D<T>& MyFinally(T t) { return D<T>(t); }
You can fix it my introducing a move constructor
template<typename T>
class D{
T fn;
bool exec;
public:
D(T v):fn(move(v)),exec(true){}
D(D &&d):fn(move(d.fn)), exec(d.exec) {
d.exec = false;
}
~D(){if(exec) fn();}
};
And then you can rewrite your toy
template<typename T>
D<T> MyFinally(T t) { return D<T>(move(t)); }
Hope it helps. No "const reference" trick is needed when you work with auto. See here for how to do it in C++03 with const references.
Your code and Sutter's are not equivalent. His function returns a value, yours returns a reference to an object that will be destroyed when the function exits. The const reference in the calling code does not maintain the lifetime of that object.
The problem stems from the use of a function maker, as demonstrated by Johannes.
I would argue that you could avoid the issue by using another C++0x facility, namely std::function.
class Defer
{
public:
typedef std::function<void()> Executor;
Defer(): _executor(DoNothing) {}
Defer(Executor e): _executor(e) {}
~Defer() { _executor(); }
Defer(Defer&& rhs): _executor(rhs._executor) {
rhs._executor = DoNothing;
}
Defer& operator=(Defer rhs) {
std::swap(_executor, rhs._executor);
return *this;
}
Defer(Defer const&) = delete;
private:
static void DoNothing() {}
Executor _executor;
};
Then, you can use it as simply:
void A::start() {
a = 1;
Defer const defer([&]() { a = 2; });
try { assert(a == 1); /**/ } catch(...) { /**/ }
}
Well the problem is explained by others, so I will suggest a fix, exactly in the same way Herb Sutter has written his code (your code is not same as his, by the way):
First, don't return by const reference:
template<typename T>
D<T> MyFinally(T t)
{
D<T> local(t); //create a local variable
return local;
}
Then write this at call site:
const auto & v = MyFinally([&]{a=2;}); //store by const reference
This became exactly like Herb Sutter's code.
Demo : http://www.ideone.com/uSkhP
Now the destructor is called just before exiting the start() function.
A different implementation which doesn't use auto keyword anymore:
struct base { virtual ~base(){} };
template<typename TLambda>
struct exec : base
{
TLambda lambda;
exec(TLambda l) : lambda(l){}
~exec() { lambda(); }
};
class lambda{
base *pbase;
public:
template<typename TLambda>
lambda(TLambda l): pbase(new exec<TLambda>(l)){}
~lambda() { delete pbase; }
};
And use it as:
lambda finally = [&]{a=2; std::cout << "finally executed" << std::endl; };
Looks interesting?
Complete demo : http://www.ideone.com/DYqrh
You could return a shared_ptr:
template<typename T>
std::shared_ptr<D<T>> MyFinally(T t) {
return std::shared_ptr<D<T>>(new D<T>(t));
}
Following code does NOT work, but it expresses well what I wish to do. There is a problem with the template struct container, which I think SHOULD work because it's size is known for any template argument.
class callback {
public:
// constructs a callback to a method in the context of a given object
template<class C>
callback(C& object, void (C::*method)())
: ptr.o(object), ptr.m(method) {}
// calls the method
void operator()() {
(&ptr.o ->* ptr.m) ();
}
private:
// container for the pointer to method
template<class C>
struct {
C& o;
void (C::*m)();
} ptr;
};
Is there any way to do such a thing? I mean have a non-template class callback which wraps any pointer to method?
Thanks C++ gurus!
Edit:
Please see this:
Callback in C++, template member? (2)
This is a complete working example that does what I think you're trying to do:
#include <iostream>
#include <memory>
// INTERNAL CLASSES
class CallbackSpecBase
{
public:
virtual ~CallbackSpecBase() {}
virtual void operator()() const = 0;
};
template<class C>
class CallbackSpec : public CallbackSpecBase
{
public:
CallbackSpec(C& o, void (C::*m)()) : obj(o), method(m) {}
void operator()() const { (&obj->*method)(); }
private:
C& obj;
void (C::*method)();
};
// PUBLIC API
class Callback
{
public:
Callback() {}
void operator()() { (*spec)(); }
template<class C>
void set(C& o, void (C::*m)()) { spec.reset(new CallbackSpec<C>(o, m)); }
private:
std::auto_ptr<CallbackSpecBase> spec;
};
// TEST CODE
class Test
{
public:
void foo() { std::cout << "Working" << std::endl; }
void bar() { std::cout << "Like a charm" << std::endl; }
};
int main()
{
Test t;
Callback c;
c.set(t, &Test::foo);
c();
c.set(t, &Test::bar);
c();
}
I recently implemented this:
#define UNKOWN_ITEM 0xFFFFFFFF
template <typename TArg>
class DelegateI
{
public:
virtual void operator()(TArg& a)=0;
virtual bool equals(DelegateI<TArg>* d)=0;
};
template <class TArg>
class Event
{
public:
Event()
{
}
~Event()
{
for (size_t x=0; x<m_vDelegates.size(); x++)
delete m_vDelegates[x];
}
void operator()(TArg& a)
{
for (size_t x=0; x<m_vDelegates.size(); x++)
{
m_vDelegates[x]->operator()(a);
}
}
void operator+=(DelegateI<TArg>* d)
{
if (findInfo(d) != UNKOWN_ITEM)
{
delete d;
return;
}
m_vDelegates.push_back(d);
}
void operator-=(DelegateI<TArg>* d)
{
uint32 index = findInfo(d);
delete d;
if (index == UNKOWN_ITEM)
return;
m_vDelegates.erase(m_vDelegates.begin()+index);
}
protected:
int findInfo(DelegateI<TArg>* d)
{
for (size_t x=0; x<m_vDelegates.size(); x++)
{
if (m_vDelegates[x]->equals(d))
return (int)x;
}
return UNKOWN_ITEM;
}
private:
std::vector<DelegateI<TArg>*> m_vDelegates;
};
template <class TObj, typename TArg>
class ObjDelegate : public DelegateI<TArg>
{
public:
typedef void (TObj::*TFunct)(TArg&);
ObjDelegate(TObj* t, TFunct f)
{
m_pObj = t;
m_pFunct = f;
}
virtual bool equals(DelegateI<TArg>* di)
{
ObjDelegate<TObj,TArg> *d = dynamic_cast<ObjDelegate<TObj,TArg>*>(di);
if (!d)
return false;
return ((m_pObj == d->m_pObj) && (m_pFunct == d->m_pFunct));
}
virtual void operator()(TArg& a)
{
if (m_pObj && m_pFunct)
{
(*m_pObj.*m_pFunct)(a);
}
}
TFunct m_pFunct; // pointer to member function
TObj* m_pObj; // pointer to object
};
template <typename TArg>
class FunctDelegate : public DelegateI<TArg>
{
public:
typedef void (*TFunct)(TArg&);
FunctDelegate(TFunct f)
{
m_pFunct = f;
}
virtual bool equals(DelegateI<TArg>* di)
{
FunctDelegate<TArg> *d = dynamic_cast<FunctDelegate<TArg>*>(di);
if (!d)
return false;
return (m_pFunct == d->m_pFunct);
}
virtual void operator()(TArg& a)
{
if (m_pFunct)
{
(*m_pFunct)(a);
}
}
TFunct m_pFunct; // pointer to member function
};
template <typename TArg>
class ProxieDelegate : public DelegateI<TArg>
{
public:
ProxieDelegate(Event<TArg>* e)
{
m_pEvent = e;
}
virtual bool equals(DelegateI<TArg>* di)
{
ProxieDelegate<TArg> *d = dynamic_cast<ProxieDelegate<TArg>*>(di);
if (!d)
return false;
return (m_pEvent == d->m_pEvent);
}
virtual void operator()(TArg& a)
{
if (m_pEvent)
{
(*m_pEvent)(a);
}
}
Event<TArg>* m_pEvent; // pointer to member function
};
template <class TObj, class TArg>
DelegateI<TArg>* delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArg&))
{
return new ObjDelegate<TObj, TArg>(pObj, NotifyMethod);
}
template <class TArg>
DelegateI<TArg>* delegate(void (*NotifyMethod)(TArg&))
{
return new FunctDelegate<TArg>(NotifyMethod);
}
template <class TArg>
DelegateI<TArg>* delegate(Event<TArg>* e)
{
return new ProxieDelegate<TArg>(e);
}
use it like so:
define:
Event<SomeClass> someEvent;
enlist callbacks:
someEvent += delegate(&someFunction);
someEvent += delegate(classPtr, &class::classFunction);
someEvent += delegate(&someOtherEvent);
trigger:
someEvent(someClassObj);
You can also make your own delegates and overide what they do. I made a couple of others with one being able to make sure the event triggers the function in the gui thread instead of the thread it was called.
You need to use polymorphism. Use an abstract base class with a virtual invocation method (operator() if you please), with a templated descendant that implements the virtual method using the correct type signature.
The way you have it now, the data holding the type is templated, but the code meant to invoke the method and pass the object isn't. That won't work; the template type parameters need to flow through both construction and invocation.
#Barry Kelly
#include <iostream>
class callback {
public:
virtual void operator()() {};
};
template<class C>
class callback_specialization : public callback {
public:
callback_specialization(C& object, void (C::*method)())
: o(object), m(method) {}
void operator()() {
(&o ->* m) ();
}
private:
C& o;
void (C::*m)();
};
class X {
public:
void y() { std::cout << "ok\n"; }
};
int main() {
X x;
callback c(callback_specialization<X>(x, &X::y));
c();
return 0;
}
I tried this, but it does not work (print "ok")... why?
Edit:
As Neil Butterworth mentioned, polymorphism works through pointers and references,
X x;
callback& c = callback_specialization<X>(x, &X::y);
c();
Edit:
With this code, I get an error:
invalid initialization of non-const reference of type ‘callback&’
from a temporary of type ‘callback_specialization<X>’
Now, I don't understand that error, but if I replace callback& c with const callback& c and virtual void operator()() with virtual void operator()() const, it works.
You didn't say what errors you found, but I found that this worked:
template<typename C>
class callback {
public:
// constructs a callback to a method in the context of a given object
callback(C& object, void (C::*method)())
: ptr(object,method) {}
// calls the method
void operator()() {
(&ptr.o ->* ptr.m) ();
}
private:
// container for the pointer to method
// template<class C>
struct Ptr{
Ptr(C& object, void (C::*method)()): o(object), m(method) {}
C& o;
void (C::*m)();
} ptr;
};
Note that Ptr needs a constructor as it has a reference member.
You could do without struct Ptr and have the raw members.
Tested with VS2008 express.
Improving the OP's answer:
int main() {
X x;
callback_specialization<X> c(x, &X::y);
callback& ref(c);
c();
return 0;
}
This prints "ok".
Tested on VS2008 express.
Please see this
Callback in C++, template member? (2)