// Boost.TypeErasure library // // Copyright 2011 Steven Watanabe // // Distributed under the Boost Software License Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // $Id: normalize.hpp 83251 2013-03-02 19:23:44Z steven_watanabe $ #ifndef BOOST_TYPE_ERASURE_DETAIL_NORMALIZE_HPP_INCLUDED #define BOOST_TYPE_ERASURE_DETAIL_NORMALIZE_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace type_erasure { template struct deduced; template struct same_type; namespace detail { struct substitution_map_tag {}; // a wrapper around an mpl::map that // defaults to the identity map. template struct substitution_map { typedef substitution_map_tag tag; typedef M map_type; }; } } namespace mpl { template<> struct at_impl< ::boost::type_erasure::detail::substitution_map_tag> { template struct apply { typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::mpl::at, ::boost::mpl::identity >::type type; }; }; template<> struct has_key_impl< ::boost::type_erasure::detail::substitution_map_tag> { template struct apply : boost::mpl::true_ {}; }; } namespace type_erasure { namespace detail { // given a partial substitution map from same_type, // resolves a placeholder as far as possible. template struct resolve_same_type { typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::type_erasure::detail::resolve_same_type< M, typename ::boost::mpl::at::type >, ::boost::mpl::identity >::type type; }; // Given the arguments to same_type, determines // which should be the key and which should be // the value in the substitution map. template struct select_pair { BOOST_MPL_ASSERT((::boost::is_same)); typedef void type; }; template struct select_pair > { typedef ::boost::mpl::pair< ::boost::type_erasure::deduced, T> type; }; template struct select_pair< ::boost::type_erasure::deduced, U> { typedef ::boost::mpl::pair< ::boost::type_erasure::deduced, U> type; }; template struct select_pair< ::boost::type_erasure::deduced, ::boost::type_erasure::deduced > { typedef ::boost::mpl::pair< ::boost::type_erasure::deduced, ::boost::type_erasure::deduced > type; }; // M is a map of placeholder substitutions template struct normalize_placeholder { typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::type_erasure::detail::normalize_placeholder< M, typename ::boost::mpl::at::type >, ::boost::mpl::identity >::type type; }; template struct normalize_placeholder > { typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::type_erasure::detail::normalize_placeholder< M, typename ::boost::mpl::at::type >, ::boost::type_erasure::detail::normalize_deduced< M, T > >::type type; }; // Takes a mpl::map of placeholder substitutions and // fully resolves it. i.e. a -> b, b -> c, becomes // a -> c, b -> c. Also resolves deduced placeholders // whose arguments are all resolved. template struct create_placeholder_map { typedef typename ::boost::mpl::fold< M, ::boost::mpl::map0<>, ::boost::mpl::insert< ::boost::mpl::_1, ::boost::mpl::pair< ::boost::mpl::first< ::boost::mpl::_2>, ::boost::type_erasure::detail::normalize_placeholder > > > >::type type; }; template struct convert_deduced { typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument< typename P::first, Bindings >::type result1; typedef typename ::boost::mpl::at::type result; typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::mpl::identity, ::boost::mpl::insert > >::type type; BOOST_MPL_ASSERT((boost::is_same::type, result>)); }; template struct convert_deductions { typedef typename ::boost::mpl::fold< M, Bindings, ::boost::type_erasure::detail::convert_deduced< Bindings, ::boost::mpl::_2, ::boost::mpl::_1, Sub > >::type type; }; template struct add_deduced { typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument< typename P::first, Bindings >::type result; typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, ::boost::mpl::identity, ::boost::mpl::insert > >::type type; BOOST_MPL_ASSERT((boost::is_same::type, result>)); }; template struct add_deductions { typedef typename ::boost::mpl::fold< M, Bindings, ::boost::type_erasure::detail::add_deduced< Bindings, ::boost::mpl::_2, ::boost::mpl::_1 > >::type type; }; // Fold Op for normalize_concept_impl template struct insert_concept { typedef ::boost::mpl::pair< typename ::boost::mpl::insert::type, typename Out::second > type; }; template struct insert_concept > { typedef typename ::boost::type_erasure::detail::resolve_same_type< typename Out::second, T >::type t1; typedef typename ::boost::type_erasure::detail::resolve_same_type< typename Out::second, U >::type t2; typedef ::boost::mpl::pair< typename Out::first, typename ::boost::mpl::eval_if< ::boost::is_same, ::boost::mpl::identity, ::boost::mpl::insert< typename Out::second, typename ::boost::type_erasure::detail::select_pair< t1, t2 >::type > >::type > type; }; // flattens a concept returning an mpl::pair // - first is an MPL sequence containing the leaf concepts // - second is an MPL map of the placeholder substitutions // used to resolve same_type. template, ::boost::mpl::map0<> > > struct normalize_concept_impl { typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence, ::boost::mpl::fold >, ::boost::type_erasure::detail::insert_concept >::type type; }; struct append_typeinfo { template struct apply { typedef typename ::boost::mpl::insert< Set, ::boost::type_erasure::typeid_ >::type type; }; }; // Seq should be a flattened MPL sequence of leaf concepts. // adds typeid_

for every placeholder used. template struct add_typeinfo { typedef typename ::boost::mpl::fold< Seq, ::boost::mpl::set0<>, ::boost::type_erasure::detail::get_placeholders< ::boost::mpl::_2, ::boost::mpl::_1 > >::type placeholders; typedef typename ::boost::mpl::fold< placeholders, Seq, ::boost::type_erasure::detail::append_typeinfo >::type type; }; template struct get_placeholder_normalization_map { typedef typename ::boost::type_erasure::detail::create_placeholder_map< typename normalize_concept_impl::type::second >::type type; }; // Flattens a Concept to an mpl::vector of primitive // concepts. Resolves same_type and deduced placeholders. template struct normalize_concept { typedef typename normalize_concept_impl::type impl; typedef typename ::boost::type_erasure::detail::create_placeholder_map< typename impl::second >::type substitutions; typedef typename ::boost::mpl::fold< typename impl::first, ::boost::mpl::set0<>, ::boost::mpl::insert< ::boost::mpl::_1, ::boost::type_erasure::detail::rebind_placeholders< ::boost::mpl::_2, ::boost::type_erasure::detail::substitution_map > > >::type basic; typedef typename ::boost::mpl::eval_if< ::boost::type_erasure::is_relaxed, ::boost::type_erasure::detail::add_typeinfo, ::boost::mpl::identity >::type concept_set; typedef typename ::boost::mpl::copy< concept_set, ::boost::mpl::back_inserter< ::boost::mpl::vector0<> > >::type type; }; // Returns an MPL sequence containing all the concepts // in Concept. If Concept is considered as a DAG, // the result will be sorted topologically. template< class Concept, class Map = typename ::boost::type_erasure::detail::create_placeholder_map< typename ::boost::type_erasure::detail::normalize_concept_impl< Concept >::type::second >::type, class Out = ::boost::mpl::set0<> > struct collect_concepts { typedef typename ::boost::type_erasure::detail::rebind_placeholders< Concept, ::boost::type_erasure::detail::substitution_map >::type transformed; typedef typename ::boost::mpl::eval_if< ::boost::is_same, ::boost::mpl::identity, ::boost::mpl::insert< Out, transformed > >::type type1; typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence, ::boost::mpl::fold >, ::boost::mpl::identity >::type type; }; } } } #endif