// copyright christoph.heindl@gmail.com 2009 #ifndef WIDEST_CONVERTIBLE_HPP #define WIDEST_CONVERTIBLE_HPP #include #include #include namespace boost { namespace detail { // Defines the forward mapping of category to constant id template struct traversal_category_to_id { BOOST_STATIC_ASSERT((false)); }; // Defines the backward mapping of constant id to category type template struct id_to_traversal_category { BOOST_STATIC_ASSERT((false)); }; // Generates a forward and backward mapping for a given category and id // Mappings a template specializations of id_to_traversal_category and // traversal_category_to_id. #define BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(Cat, Id) \ template<> \ struct traversal_category_to_id < Cat > { \ static unsigned long const value = Id; \ }; \ template<> \ struct id_to_traversal_category < Id > { \ typedef Cat type; \ }; // Carefully choose the mappings BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(::boost::incrementable_traversal_tag, 1) BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(::boost::single_pass_traversal_tag, 2) BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(::boost::forward_traversal_tag, 4) BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(::boost::bidirectional_traversal_tag, 8) BOOST_TRAVERSAL_CATEGORY_ID_MAPPING(::boost::random_access_traversal_tag, 16) } // Derive the widest convertible iterator traversal category of // two given traversal categories. // // The problem is reformulated as a a 'greatest common divisor' problem by // building a mapping from category to ids. The ids are chosen to be the powers of two, where // 2^0 is assigned to incrementable_traversal_tag, 2^1 to single_pass_traversal_tag, etc. template struct widest_convertible_traversal_cat { typedef typename detail::id_to_traversal_category< math::static_gcd< detail::traversal_category_to_id::value, detail::traversal_category_to_id::value >::value >::type type; }; } #endif //TRAVERSAL_CATEGORIES_HPP