// Copyright (c) 2004 Daniel Wallin // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include #include #include #include struct base {}; struct A : base {}; struct B : A {}; struct C : B {}; struct handler; typedef std::vector handlers_t; struct handler { virtual handlers_t::iterator try_( boost::function0 const& fn , handlers_t::iterator iter , handlers_t::iterator end ) = 0; virtual void print_type() const = 0; }; template struct handler_impl : handler { handlers_t::iterator try_( boost::function0 const& fn , handlers_t::iterator iter , handlers_t::iterator end) { try { if (iter == (end - 1)) { fn(); } else { handlers_t::iterator next(iter); ++next; return (*next)->try_(fn, next, end); } } catch (T const*) { return iter; } } void print_type() const { std::cout << typeid(T).name() << "\n"; } }; template struct throw_ { void operator()() const { T* p(0); throw p; } }; handlers_t& handlers() { static handlers_t h; return h; } template void register_() { handlers_t::iterator iter = handlers().end(); if (handlers().empty()) { handlers().push_back(new handler_impl); return; } try { iter = handlers()[0]->try_(throw_(), handlers().begin(), handlers().end()); handlers().insert(iter + 1, new handler_impl); } catch (T const*) { handlers().insert(handlers().begin(), new handler_impl); } } int main() { register_(); register_(); register_(); register_(); std::cout << "-- order -----------------------------\n"; std::for_each( handlers().begin() , handlers().end() , boost::bind(&handler::print_type, _1) ); }