Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/type_erasure/binding.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Boost.TypeErasure library
0002 //
0003 // Copyright 2011 Steven Watanabe
0004 //
0005 // Distributed under the Boost Software License Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // $Id$
0010 
0011 #ifndef BOOST_TYPE_ERASURE_BINDING_HPP_INCLUDED
0012 #define BOOST_TYPE_ERASURE_BINDING_HPP_INCLUDED
0013 
0014 #include <boost/config.hpp>
0015 #include <boost/shared_ptr.hpp>
0016 #include <boost/make_shared.hpp>
0017 #include <boost/utility/enable_if.hpp>
0018 #include <boost/mpl/transform.hpp>
0019 #include <boost/mpl/find_if.hpp>
0020 #include <boost/mpl/and.hpp>
0021 #include <boost/mpl/not.hpp>
0022 #include <boost/mpl/end.hpp>
0023 #include <boost/mpl/bool.hpp>
0024 #include <boost/mpl/pair.hpp>
0025 #include <boost/type_traits/is_same.hpp>
0026 #include <boost/type_erasure/static_binding.hpp>
0027 #include <boost/type_erasure/is_subconcept.hpp>
0028 #include <boost/type_erasure/detail/adapt_to_vtable.hpp>
0029 #include <boost/type_erasure/detail/null.hpp>
0030 #include <boost/type_erasure/detail/rebind_placeholders.hpp>
0031 #include <boost/type_erasure/detail/vtable.hpp>
0032 #include <boost/type_erasure/detail/normalize.hpp>
0033 #include <boost/type_erasure/detail/instantiate.hpp>
0034 #include <boost/type_erasure/detail/check_map.hpp>
0035 
0036 namespace boost {
0037 namespace type_erasure {
0038 
0039 template<class P>
0040 class dynamic_binding;
0041 
0042 namespace detail {
0043 
0044 template<class Source, class Dest, class Map>
0045 struct can_optimize_conversion : ::boost::mpl::and_<
0046     ::boost::is_same<Source, Dest>,
0047         ::boost::is_same<
0048             typename ::boost::mpl::find_if<
0049                 Map,
0050                 ::boost::mpl::not_<
0051                     ::boost::is_same<
0052                         ::boost::mpl::first< ::boost::mpl::_1>,
0053                         ::boost::mpl::second< ::boost::mpl::_1>
0054                     >
0055                 >
0056             >::type,
0057             typename ::boost::mpl::end<Map>::type
0058         >
0059     >::type
0060 {};
0061 
0062 }
0063 
0064 /**
0065  * Stores the binding of a @c Concept to a set of actual types.
0066  * @c Concept is interpreted in the same way as with @ref any.
0067  */
0068 template<class Concept>
0069 class binding
0070 {
0071     typedef typename ::boost::type_erasure::detail::normalize_concept<
0072         Concept>::type normalized;
0073     typedef typename ::boost::mpl::transform<normalized,
0074         ::boost::type_erasure::detail::maybe_adapt_to_vtable< ::boost::mpl::_1>
0075     >::type actual_concept;
0076     typedef typename ::boost::type_erasure::detail::make_vtable<
0077         actual_concept>::type table_type;
0078     typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
0079         Concept
0080     >::type placeholder_subs;
0081 public:
0082 
0083     /**
0084      * \pre @ref relaxed must be in @c Concept.
0085      *
0086      * \throws Nothing.
0087      */
0088     binding() { BOOST_MPL_ASSERT((::boost::type_erasure::is_relaxed<Concept>)); }
0089     
0090     /**
0091      * \pre @c Map must be an MPL map with an entry for each placeholder
0092      *      referred to by @c Concept.
0093      *
0094      * \throws Nothing.
0095      */
0096     template<class Map>
0097     explicit binding(const Map&)
0098       : impl((
0099             BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map),
0100             static_binding<Map>()
0101         ))
0102     {}
0103     
0104     /**
0105      * \pre @c Map must be an MPL map with an entry for each placeholder
0106      *      referred to by @c Concept.
0107      *
0108      * \throws Nothing.
0109      */
0110     template<class Map>
0111     binding(const static_binding<Map>&)
0112       : impl((
0113             BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map),
0114             static_binding<Map>()
0115         ))
0116     {}
0117 
0118     /**
0119      * Converts from another set of bindings.
0120      *
0121      * \pre Map must be an MPL map with an entry for each placeholder
0122      *      referred to by @c Concept.  The mapped type should be the
0123      *      corresponding placeholder in Concept2.
0124      *
0125      * \throws std::bad_alloc
0126      */
0127     template<class Concept2, class Map>
0128     binding(const binding<Concept2>& other, const Map&
0129 #ifndef BOOST_TYPE_ERASURE_DOXYGEN
0130         , typename ::boost::enable_if<
0131             ::boost::mpl::and_<
0132                 ::boost::type_erasure::detail::check_map<Concept, Map>,
0133                 ::boost::type_erasure::is_subconcept<Concept, Concept2, Map>
0134             >
0135         >::type* = 0
0136 #endif
0137         )
0138       : impl(
0139             other,
0140             static_binding<Map>(),
0141             ::boost::type_erasure::detail::can_optimize_conversion<Concept2, Concept, Map>()
0142         )
0143     {}
0144 
0145     /**
0146      * Converts from another set of bindings.
0147      *
0148      * \pre Map must be an MPL map with an entry for each placeholder
0149      *      referred to by @c Concept.  The mapped type should be the
0150      *      corresponding placeholder in Concept2.
0151      *
0152      * \throws std::bad_alloc
0153      */
0154     template<class Concept2, class Map>
0155     binding(const binding<Concept2>& other, const static_binding<Map>&
0156 #ifndef BOOST_TYPE_ERASURE_DOXYGEN
0157         , typename ::boost::enable_if<
0158             ::boost::mpl::and_<
0159                 ::boost::type_erasure::detail::check_map<Concept, Map>,
0160                 ::boost::type_erasure::is_subconcept<Concept, Concept2, Map>
0161             >
0162         >::type* = 0
0163 #endif
0164         )
0165       : impl(
0166             other,
0167             static_binding<Map>(),
0168             ::boost::type_erasure::detail::can_optimize_conversion<Concept2, Concept, Map>()
0169         )
0170     {}
0171 
0172     /**
0173      * Converts from another set of bindings.
0174      *
0175      * \pre Map must be an MPL map with an entry for each placeholder
0176      *      referred to by @c Concept.  The mapped type should be the
0177      *      corresponding placeholder in Concept2.
0178      *
0179      * \throws std::bad_alloc
0180      * \throws std::bad_any_cast
0181      */
0182     template<class Placeholders, class Map>
0183     binding(const dynamic_binding<Placeholders>& other, const static_binding<Map>&)
0184       : impl(
0185             other,
0186             static_binding<Map>()
0187         )
0188     {}
0189 
0190     /**
0191      * \return true iff the sets of types that the placeholders
0192      *         bind to are the same for both arguments.
0193      *
0194      * \throws Nothing.
0195      */
0196     friend bool operator==(const binding& lhs, const binding& rhs)
0197     { return *lhs.impl.table == *rhs.impl.table; }
0198     
0199     /**
0200      * \return true iff the arguments do not map to identical
0201      *         sets of types.
0202      *
0203      * \throws Nothing.
0204      */
0205     friend bool operator!=(const binding& lhs, const binding& rhs)
0206     { return !(lhs == rhs); }
0207 
0208     /** INTERNAL ONLY */
0209     template<class T>
0210     typename T::type find() const { return impl.table->lookup((T*)0); }
0211 private:
0212     template<class C2>
0213     friend class binding;
0214     template<class P>
0215     friend class dynamic_binding;
0216     /** INTERNAL ONLY */
0217     struct impl_type
0218     {
0219         impl_type() {
0220             table = &::boost::type_erasure::detail::make_vtable_init<
0221                 typename ::boost::mpl::transform<
0222                     actual_concept,
0223                     ::boost::type_erasure::detail::get_null_vtable_entry<
0224                         ::boost::mpl::_1
0225                     >
0226                 >::type,
0227                 table_type
0228             >::type::value;
0229         }
0230         template<class Map>
0231         impl_type(const static_binding<Map>&)
0232         {
0233             table = &::boost::type_erasure::detail::make_vtable_init<
0234                 typename ::boost::mpl::transform<
0235                     actual_concept,
0236                     ::boost::type_erasure::detail::rebind_placeholders<
0237                         ::boost::mpl::_1,
0238                         typename ::boost::type_erasure::detail::add_deductions<
0239                             Map,
0240                             placeholder_subs
0241                         >::type
0242                     >
0243                 >::type,
0244                 table_type
0245             >::type::value;
0246         }
0247         template<class Concept2, class Map>
0248         impl_type(const binding<Concept2>& other, const static_binding<Map>&, boost::mpl::false_)
0249           : manager(new table_type)
0250         {
0251             manager->template convert_from<
0252                 typename ::boost::type_erasure::detail::convert_deductions<
0253                     Map,
0254                     placeholder_subs,
0255                     typename binding<Concept2>::placeholder_subs
0256                 >::type
0257             >(*other.impl.table);
0258             table = manager.get();
0259         }
0260         template<class PlaceholderList, class Map>
0261         impl_type(const dynamic_binding<PlaceholderList>& other, const static_binding<Map>&)
0262           : manager(new table_type)
0263         {
0264             manager->template convert_from<
0265                 // FIXME: What do we need to do with deduced placeholder in other
0266                 typename ::boost::type_erasure::detail::add_deductions<
0267                     Map,
0268                     placeholder_subs
0269                 >::type
0270             >(other.impl);
0271             table = manager.get();
0272         }
0273         template<class Concept2, class Map>
0274         impl_type(const binding<Concept2>& other, const static_binding<Map>&, boost::mpl::true_)
0275           : table(other.impl.table),
0276             manager(other.impl.manager)
0277         {}
0278         const table_type* table;
0279         ::boost::shared_ptr<table_type> manager;
0280     } impl;
0281 };
0282 
0283 }
0284 }
0285 
0286 #endif