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( q, this, std::forward(of)); } ~TemplateDispatcher() noexcept(false) { if (!chained) { wait_and_dispatch(); } } }; } // namespace messaging