1 // (C) Copyright Jeremy Siek 2004
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_PROPERTY_HPP
7 #define BOOST_PROPERTY_HPP
9 #include <boost/pending/ct_if.hpp>
14 typedef no_property tag_type
;
15 typedef no_property next_type
;
16 typedef no_property value_type
;
21 template <class Tag
, class T
, class Base
= no_property
>
22 struct property
: public Base
{
23 typedef Base next_type
;
26 #if BOOST_WORKAROUND (__GNUC__, < 3)
29 property() : m_value() { }
31 property(const T
& v
) : m_value(v
) { }
32 property(const T
& v
, const Base
& b
) : Base(b
), m_value(v
) { }
33 // copy constructor and assignment operator will be generated by compiler
38 // The BGL properties specialize property_kind and
39 // property_num, and use enum's for the Property type (see
40 // graph/properties.hpp), but the user may want to use a class
41 // instead with a nested kind type and num. Also, we may want to
42 // switch BGL back to using class types for properties at some point.
44 template <class PropertyTag
>
45 struct property_kind
{
46 typedef typename
PropertyTag::kind type
;
51 BOOST_STATIC_CONSTANT(bool, value
= true);
52 typedef true_type type
;
55 struct has_property
<no_property
> {
56 BOOST_STATIC_CONSTANT(bool, value
= false);
57 typedef false_type type
;
62 #include <boost/pending/detail/property.hpp>
66 template <class PropertyList
, class Tag
>
67 struct property_value
{
68 #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
69 typedef typename
detail::build_property_tag_value_alist
<PropertyList
>::type AList
;
70 typedef typename
detail::extract_value
<AList
,Tag
>::type type
;
72 typedef typename
detail::build_property_tag_value_alist
<PropertyList
>::type AList
;
73 typedef typename
detail::ev_selector
<AList
>::type Extractor
;
74 typedef typename
Extractor::template bind_
<AList
,Tag
>::type type
;
79 inline detail::error_property_not_found
80 get_property_value(const no_property
& p
, Tag2
) {
81 return detail::error_property_not_found();
84 template <class Tag1
, class Tag2
, class T1
, class Base
>
85 inline typename property_value
<property
<Tag1
,T1
,Base
>, Tag2
>::type
&
86 get_property_value(property
<Tag1
,T1
,Base
>& p
, Tag2 tag2
) {
87 BOOST_STATIC_CONSTANT(bool,
88 match
= (detail::same_property
<Tag1
,Tag2
>::value
));
89 typedef property
<Tag1
,T1
,Base
> Prop
;
90 typedef typename property_value
<Prop
, Tag2
>::type T2
;
92 typedef detail::property_value_dispatch
<match
> Dispatcher
;
93 return Dispatcher::get_value(p
, t2
, tag2
);
95 template <class Tag1
, class Tag2
, class T1
, class Base
>
97 const typename property_value
<property
<Tag1
,T1
,Base
>, Tag2
>::type
&
98 get_property_value(const property
<Tag1
,T1
,Base
>& p
, Tag2 tag2
) {
99 BOOST_STATIC_CONSTANT(bool,
100 match
= (detail::same_property
<Tag1
,Tag2
>::value
));
101 typedef property
<Tag1
,T1
,Base
> Prop
;
102 typedef typename property_value
<Prop
, Tag2
>::type T2
;
104 typedef detail::property_value_dispatch
<match
> Dispatcher
;
105 return Dispatcher::const_get_value(p
, t2
, tag2
);
110 /** This trait returns true if T is no_property. */
111 template <typename T
>
112 struct is_no_property
113 : mpl::bool_
<is_same
<T
, no_property
>::value
>
116 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
117 /** @internal @name Retag Property List
118 * This metafunction is used internally to normalize a property if it is
119 * actually modeling a property. Specifically this is used in Boost.Graph
120 * to map user-provided classes into bundled properties.
123 // One base case of the recursive form (see below). This matches any
124 // retag request that does not include a property<...> or no_property as
125 // the FinalType. This is used for generating bundles in Boost.Graph.
126 template<typename FinalTag
, typename FinalType
>
127 struct retag_property_list
129 typedef property
<FinalTag
, FinalType
> type
;
130 typedef FinalType retagged
;
133 // Recursively retag the nested property list.
134 template<typename FinalTag
, typename Tag
, typename T
, typename Base
>
135 struct retag_property_list
<FinalTag
, property
<Tag
, T
, Base
> >
138 typedef retag_property_list
<FinalTag
, Base
> next
;
141 typedef property
<Tag
, T
, typename
next::type
> type
;
142 typedef typename
next::retagged retagged
;
145 // This base case will correctly deduce the final property type if the
146 // retagged property is given in property form. This should not hide
147 // the base case below.
148 // NOTE: This addresses a problem of layering bundled properties in the BGL
149 // where multiple retaggings will fail to deduce the correct retagged
151 template<typename FinalTag
, typename FinalType
>
152 struct retag_property_list
<FinalTag
, property
<FinalTag
, FinalType
> >
155 typedef property
<FinalTag
, FinalType
> type
;
156 typedef FinalType retagged
;
159 // A final base case of the retag_propert_list, this will terminate a
160 // properly structured list.
161 template<typename FinalTag
>
162 struct retag_property_list
<FinalTag
, no_property
>
164 typedef no_property type
;
165 typedef no_property retagged
;
169 } // namespace detail
173 #endif /* BOOST_PROPERTY_HPP */