namespace messaging { template class TemplateDispatcher { queue* q; PreviousDispatcher* prev; Func f; bool chained; TemplateDispatcher(TemplateDispatcher const&)=delete; TemplateDispatcher& operator=(TemplateDispatcher const&)=delete; template friend class TemplateDispatcher; void wait_and_dispatch() { for(;;) { auto msg=q->wait_and_pop(); if(dispatch(msg)) break; } } bool dispatch(std::shared_ptr const& msg) { if(wrapped_message* wrapper= dynamic_cast*>(msg.get())) { f(wrapper->contents); return true; } else { return prev->dispatch(msg); } } public: TemplateDispatcher(TemplateDispatcher&& other): q(other.q),prev(other.prev),f(std::move(other.f)), chained(other.chained) { other.chained=true; } TemplateDispatcher(queue* q_,PreviousDispatcher* prev_,Func&& f_): q(q_),prev(prev_),f(std::forward(f_)),chained(false) { prev_->chained=true; } template TemplateDispatcher handle(OtherFunc&& of) { return TemplateDispatcher< TemplateDispatcher,OtherMsg,OtherFunc>( q,this,std::forward(of)); } ~TemplateDispatcher() noexcept(false) { if(!chained) { wait_and_dispatch(); } } }; }