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