sl@0: // (C) Copyright Jeremy Siek 2004 sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: #ifndef BOOST_DETAIL_PROPERTY_HPP sl@0: #define BOOST_DETAIL_PROPERTY_HPP sl@0: sl@0: #include // for std::pair sl@0: #include // for is_same sl@0: sl@0: namespace boost { sl@0: sl@0: namespace detail { sl@0: sl@0: template sl@0: struct same_property { sl@0: enum { value = is_same::value }; sl@0: }; sl@0: sl@0: struct error_property_not_found { }; sl@0: sl@0: template sl@0: struct property_value_dispatch { sl@0: template sl@0: inline static T& get_value(PropertyTag& p, T*, Tag) { sl@0: return p.m_value; sl@0: } sl@0: template sl@0: inline static const T& const_get_value(const PropertyTag& p, T*, Tag) { sl@0: return p.m_value; sl@0: } sl@0: }; sl@0: sl@0: template sl@0: struct property_value_end { sl@0: template struct result { typedef T type; }; sl@0: sl@0: template sl@0: inline static T& get_value(PropertyList& p, T* t, Tag tag) { sl@0: typedef typename PropertyList::next_type Next; sl@0: typedef typename Next::tag_type Next_tag; sl@0: enum { match = same_property::value }; sl@0: return property_value_dispatch sl@0: ::get_value(static_cast(p), t, tag); sl@0: } sl@0: template sl@0: inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) { sl@0: typedef typename PropertyList::next_type Next; sl@0: typedef typename Next::tag_type Next_tag; sl@0: enum { match = same_property::value }; sl@0: return property_value_dispatch sl@0: ::const_get_value(static_cast(p), t, tag); sl@0: } sl@0: }; sl@0: template <> sl@0: struct property_value_end { sl@0: template struct result { sl@0: typedef detail::error_property_not_found type; sl@0: }; sl@0: sl@0: // Stop the recursion and return error sl@0: template sl@0: inline static detail::error_property_not_found& sl@0: get_value(no_property&, T*, Tag) { sl@0: static error_property_not_found s_prop_not_found; sl@0: return s_prop_not_found; sl@0: } sl@0: template sl@0: inline static const detail::error_property_not_found& sl@0: const_get_value(const no_property&, T*, Tag) { sl@0: static error_property_not_found s_prop_not_found; sl@0: return s_prop_not_found; sl@0: } sl@0: }; sl@0: sl@0: template <> sl@0: struct property_value_dispatch<0> { sl@0: template sl@0: inline static typename property_value_end::template result::type& sl@0: get_value(PropertyList& p, T* t, Tag tag) { sl@0: return property_value_end::get_value(p, t, tag); sl@0: } sl@0: template sl@0: inline static const typename property_value_end::template result::type& sl@0: const_get_value(const PropertyList& p, T* t, Tag tag) { sl@0: return property_value_end::const_get_value(p, t, tag); sl@0: } sl@0: }; sl@0: sl@0: template sl@0: struct build_property_tag_value_alist sl@0: { sl@0: typedef typename PropertyList::next_type NextProperty; sl@0: typedef typename PropertyList::value_type Value; sl@0: typedef typename PropertyList::tag_type Tag; sl@0: typedef typename build_property_tag_value_alist::type Next; sl@0: typedef std::pair< std::pair, Next> type; sl@0: }; sl@0: template <> sl@0: struct build_property_tag_value_alist sl@0: { sl@0: typedef no_property type; sl@0: }; sl@0: sl@0: #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION sl@0: template sl@0: struct extract_value { sl@0: typedef error_property_not_found type; sl@0: }; sl@0: template sl@0: struct extract_value< std::pair,Rest>, Tag2> { sl@0: typedef typename extract_value::type type; sl@0: }; sl@0: template sl@0: struct extract_value< std::pair,Rest>, Tag> { sl@0: typedef Value type; sl@0: }; sl@0: #else sl@0: // VC++ workaround: sl@0: // The main idea here is to replace partial specialization with sl@0: // nested template member classes. Of course there is the sl@0: // further complication that the outer class of the nested sl@0: // template class cannot itself be a template class. sl@0: // Hence the need for the ev_selector. -JGS sl@0: sl@0: struct recursive_extract; sl@0: struct end_extract; sl@0: sl@0: template sl@0: struct ev_selector { typedef recursive_extract type; }; sl@0: template <> sl@0: struct ev_selector { typedef end_extract type; }; sl@0: sl@0: struct recursive_extract { sl@0: template sl@0: struct bind_ { sl@0: typedef typename TagValueAList::first_type AListFirst; sl@0: typedef typename AListFirst::first_type Tag2; sl@0: typedef typename AListFirst::second_type Value; sl@0: enum { match = same_property::value }; sl@0: typedef typename TagValueAList::second_type Next; sl@0: typedef typename ev_selector::type Extractor; sl@0: typedef typename boost::ct_if< match, Value, sl@0: typename Extractor::template bind_::type sl@0: >::type type; sl@0: }; sl@0: }; sl@0: struct end_extract { sl@0: template sl@0: struct bind_ { sl@0: typedef error_property_not_found type; sl@0: }; sl@0: }; sl@0: #endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION sl@0: sl@0: } // namespace detail sl@0: } // namespace boost sl@0: sl@0: #endif // BOOST_DETAIL_PROPERTY_HPP