summaryrefslogtreecommitdiff
path: root/boost/pending/property.hpp
blob: c9880458cba518b2c59f968b2b86f0e3ec31e296 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//  (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_PROPERTY_HPP
#define BOOST_PROPERTY_HPP

#include <boost/mpl/bool.hpp>

namespace boost {

  struct no_property {
    typedef no_property tag_type;
    typedef no_property next_type;
    typedef no_property value_type;
    enum { num = 0 };
    typedef void kind;
  };

  template <class Tag, class T, class Base = no_property>
  struct property : public Base {
    typedef Base next_type;
    typedef Tag tag_type;
    typedef T value_type;
#if BOOST_WORKAROUND (__GNUC__, < 3)
    property() { }
#else
    property() : m_value() { }
#endif
    property(const T& v) : m_value(v) { }
    property(const T& v, const Base& b) : Base(b), m_value(v) { }
    // copy constructor and assignment operator will be generated by compiler

    T m_value;
  };

  // The BGL properties specialize property_kind and
  // property_num, and use enum's for the Property type (see
  // graph/properties.hpp), but the user may want to use a class
  // instead with a nested kind type and num.  Also, we may want to
  // switch BGL back to using class types for properties at some point.

  template <class PropertyTag>
  struct property_kind {
    typedef typename PropertyTag::kind type;
  };

  template <class P>
  struct has_property : boost::mpl::true_ {};
  template <>
  struct has_property<no_property> : boost::mpl::false_ {};

} // namespace boost

#include <boost/pending/detail/property.hpp>

namespace boost {

  template <class PropertyList, class Tag>
  struct property_value {
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
    typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
    typedef typename detail::extract_value<AList,Tag>::type type;
#else
    typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
    typedef typename detail::ev_selector<AList>::type Extractor;
    typedef typename Extractor::template bind_<AList,Tag>::type type;
#endif
  };

  template <class Tag2>
  inline detail::error_property_not_found
  get_property_value(const no_property&, Tag2) {
    return detail::error_property_not_found();
  }

  template <class Tag1, class Tag2, class T1, class Base>
  inline typename property_value<property<Tag1,T1,Base>, Tag2>::type&
  get_property_value(property<Tag1,T1,Base>& p, Tag2 tag2) {
    BOOST_STATIC_CONSTANT(bool,
                          match = (detail::same_property<Tag1,Tag2>::value));
    typedef property<Tag1,T1,Base> Prop;
    typedef typename property_value<Prop, Tag2>::type T2;
    T2* t2 = 0;
    typedef detail::property_value_dispatch<match> Dispatcher;
    return Dispatcher::get_value(p, t2, tag2);
  }
  template <class Tag1, class Tag2, class T1, class Base>
  inline
  const typename property_value<property<Tag1,T1,Base>, Tag2>::type&
  get_property_value(const property<Tag1,T1,Base>& p, Tag2 tag2) {
    BOOST_STATIC_CONSTANT(bool,
                          match = (detail::same_property<Tag1,Tag2>::value));
    typedef property<Tag1,T1,Base> Prop;
    typedef typename property_value<Prop, Tag2>::type T2;
    T2* t2 = 0;
    typedef detail::property_value_dispatch<match> Dispatcher;
    return Dispatcher::const_get_value(p, t2, tag2);
  }

 namespace detail {

     /** This trait returns true if T is no_property. */
    template <typename T>
    struct is_no_property
        : mpl::bool_<is_same<T, no_property>::value>
    { };

#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
    /** @internal @name Retag Property List
     * This metafunction is used internally to normalize a property if it is
     * actually modeling a property. Specifically this is used in Boost.Graph
     * to map user-provided classes into bundled properties.
     */
    //@{
    // One base case of the recursive form (see below). This matches any
    // retag request that does not include a property<...> or no_property as
    // the FinalType. This is used for generating bundles in Boost.Graph.
    template<typename FinalTag, typename FinalType>
    struct retag_property_list
    {
        typedef property<FinalTag, FinalType> type;
        typedef FinalType retagged;
    };

    // Recursively retag the nested property list.
    template<typename FinalTag, typename Tag, typename T, typename Base>
    struct retag_property_list<FinalTag, property<Tag, T, Base> >
    {
    private:
        typedef retag_property_list<FinalTag, Base> next;

    public:
        typedef property<Tag, T, typename next::type> type;
        typedef typename next::retagged retagged;
    };

    // This base case will correctly deduce the final property type if the
    // retagged property is given in property form. This should not hide
    // the base case below.
    // NOTE: This addresses a problem of layering bundled properties in the BGL
    // where multiple retaggings will fail to deduce the correct retagged
    // type.
    template<typename FinalTag, typename FinalType>
    struct retag_property_list<FinalTag, property<FinalTag, FinalType> >
    {
    public:
        typedef property<FinalTag, FinalType> type;
        typedef FinalType retagged;
    };

    // A final base case of the retag_property_list, this will terminate a
    // properly structured list.
    template<typename FinalTag>
    struct retag_property_list<FinalTag, no_property>
    {
        typedef no_property type;
        typedef no_property retagged;
    };
    //@}
#endif
} // namespace detail

} // namesapce boost

#endif /* BOOST_PROPERTY_HPP */