4
\$\begingroup\$

Just as the question states and to be sure, am I missing anything on this? Something important/obvious that I overlooked? As is, I can save any functor, function pointer and member function pointer using this delegate class (copy ctor and assignment operator left out for brevity, as were the versions with parameters).

template<class Type>
void Deleter(void* object){
 Type* obj_ptr = static_cast<Type*>(object);
 delete obj_ptr;
}
template<class Functor>
struct DelegateHelper{
 typedef typename Functor::result_type result_type;
 DelegateHelper(Functor func)
 : func_(func)
 {}
 result_type operator()(){
 return func_();
 }
 Functor func_;
};
template<class Obj, class R>
struct DelegateHelper<R (Obj::*)()>{
 typedef R (Obj::*FuncPtr)();
 DelegateHelper(Obj* obj_ptr, FuncPtr func)
 : object_(obj_ptr)
 , func_(func)
 {}
 R operator()(){
 return (object_->*func_)();
 }
 Obj* object_;
 FuncPtr func_;
};
template<class R>
struct DelegateHelper<R (*)()>{
 typedef R (*FuncPtr)();
 DelegateHelper(FuncPtr func)
 : func_(func)
 {}
 R operator()(){
 return (*func_)();
 }
 FuncPtr func_;
};
template<class Sig>
struct Delegate;
template<class R>
struct Delegate<R ()>{
 typedef R (*SinkPtr)(void*);
 Delegate()
 : object_(0)
 , func_(0)
 , deleter_(0)
 {}
 template<class F>
 Delegate(F func)
 : object_(new DelegateHelper<F>(func))
 , func_(&Sink<DelegateHelper<F> >)
 , deleter_(&Deleter<DelegateHelper<F> >)
 {}
 template<class C, class F>
 Delegate(C* obj, F func)
 : object_(new DelegateHelper<F>(obj, func))
 , func_(&Sink<DelegateHelper<F> >)
 , deleter_(&Deleter<DelegateHelper<F> >)
 {}
 ~Delegate(){
 if(deleter_)
 (*deleter_)(object_);
 }
 R operator()(){
 return (*func_)(object_);
 }
 template<class Type>
 static R Sink(void* obj_ptr){
 Type* object = (Type*)obj_ptr;
 return (*object)();
 }
 typedef void (*DeleteFunc)(void*);
 void* object_;
 SinkPtr func_;
 DeleteFunc deleter_;
};

For the delegate in effect, see here on Ideone.

Quill
12k5 gold badges41 silver badges93 bronze badges
asked Mar 22, 2011 at 16:50
\$\endgroup\$
2
  • \$\begingroup\$ Have you looked at 'Fastest possible delegates' in codeproject? It's just so you're not reinventing the wheel. \$\endgroup\$ Commented Mar 22, 2011 at 22:43
  • \$\begingroup\$ @Victor: I did, and also at the 'Impossibly fast delegates' and actually stole the idea of void pointers and type erasure using function pointers and templates from the second one, but they all seem so bloated and big, like Boost.Function, which is just huge, and that's one reason why I asked, because this implementation is actually so small that it just got me wondering. It seems that I must have missed something. \$\endgroup\$ Commented Mar 22, 2011 at 23:23

1 Answer 1

2
\$\begingroup\$

You are missing const and volatile qualified method pointer versions.

Example:

template<class Obj, class R>
struct DelegateHelper<R (Obj::*)() const>{
 typedef R (Obj::*FuncPtr)() const;
 DelegateHelper(const Obj* obj_ptr, FuncPtr func)
 : object_(obj_ptr)
 , func_(func)
 {}
 R operator()(){
 return (object_->*func_)();
 }
 const Obj* object_;
 FuncPtr func_;
};

Also, you may (probably) need specializations or internal delegates for handling of functions with void return values. Someone else may be able to fill in the details, but it seems some compilers are OK with

return function_returning_void();

And others are not.

Another thing that makes the boost version and some others larger is being able to accept & or * arguments for the object value when calling methods.

answered Mar 31, 2011 at 4:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.