1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga  2014-2014
4 //
5 // Distributed under the Boost Software License, Version 1.0.
6 //    (See accompanying file LICENSE_1_0.txt or copy at
7 //          http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // See http://www.boost.org/libs/intrusive for documentation.
10 //
11 /////////////////////////////////////////////////////////////////////////////
12 
13 #ifndef BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP
14 #define BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP
15 
16 #ifndef BOOST_CONFIG_HPP
17 #  include <boost/config.hpp>
18 #endif
19 
20 #if defined(BOOST_HAS_PRAGMA_ONCE)
21 #  pragma once
22 #endif
23 
24 #include <boost/intrusive/detail/config_begin.hpp>
25 #include <boost/intrusive/detail/mpl.hpp>
26 #include <boost/intrusive/detail/hook_traits.hpp>
27 
28 namespace boost {
29 namespace intrusive {
30 
31 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
32 
33 template<class SupposedValueTraits>
34 struct is_default_hook_tag
35 {  static const bool value = false;  };
36 
37 namespace detail{
38 
39 template <class T, class BaseHook>
40 struct concrete_hook_base_value_traits
41 {
42    typedef typename BaseHook::hooktags tags;
43    typedef bhtraits
44       < T
45       , typename tags::node_traits
46       , tags::link_mode
47       , typename tags::tag
48       , tags::type> type;
49 };
50 
51 template <class BaseHook>
52 struct concrete_hook_base_value_traits<void, BaseHook>
53 {
54    typedef typename BaseHook::hooktags type;
55 };
56 
57 template <class T, class AnyToSomeHook_ProtoValueTraits>
58 struct any_hook_base_value_traits
59 {
60    //AnyToSomeHook value_traits derive from a generic_hook
61    //The generic_hook is configured with any_node_traits
62    //and AnyToSomeHook::value_traits with the correct
63    //node traits for the container, so use node_traits
64    //from AnyToSomeHook_ProtoValueTraits and the rest of
65    //elements from the hooktags member of the generic_hook
66 
67    typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t     basic_hook_t;
68    typedef typename pointer_rebind
69       < typename basic_hook_t::hooktags::node_traits::node_ptr
70       , void>::type                                                  void_pointer;
71    typedef typename AnyToSomeHook_ProtoValueTraits::template
72       node_traits_from_voidptr<void_pointer>::type                   node_traits;
73 
74    typedef bhtraits
75       < T
76       , node_traits
77       , basic_hook_t::hooktags::link_mode
78       , typename basic_hook_t::hooktags::tag
79       , basic_hook_t::hooktags::type
80       > type;
81 };
82 
83 template <class AnyToSomeHook_ProtoValueTraits>
84 struct any_hook_base_value_traits<void, AnyToSomeHook_ProtoValueTraits>
85 {
86    typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t     basic_hook_t;
87    typedef typename pointer_rebind
88       < typename basic_hook_t::hooktags::node_traits::node_ptr
89       , void>::type                                                  void_pointer;
90 
91    struct type
92    {
93       typedef typename AnyToSomeHook_ProtoValueTraits::template
94          node_traits_from_voidptr<void_pointer>::type                node_traits;
95    };
96 };
97 
98 template<class MemberHook>
99 struct get_member_value_traits
100 {
101    typedef typename MemberHook::member_value_traits type;
102 };
103 
104 BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_any_hook, is_any_hook)
105 BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(internal_base_hook, hooktags::is_base_hook)
106 
107 template <class T>
108 struct internal_member_value_traits
109 {
110    template <class U> static yes_type test(...);
111    template <class U> static no_type test(typename U::member_value_traits* = 0);
112    static const bool value = sizeof(test<T>(0)) == sizeof(no_type);
113 };
114 
115 template<class SupposedValueTraits, class T, bool = is_default_hook_tag<SupposedValueTraits>::value>
116 struct supposed_value_traits;
117 
118 template<class T, class BaseHook, bool = internal_any_hook_bool_is_true<BaseHook>::value>
119 struct get_base_value_traits;
120 
121 template<class SupposedValueTraits, class T, bool = internal_base_hook_bool_is_true<SupposedValueTraits>::value>
122 struct supposed_base_value_traits;
123 
124 template<class SupposedValueTraits, bool = internal_member_value_traits<SupposedValueTraits>::value>
125 struct supposed_member_value_traits;
126 
127 template<class SupposedValueTraits, bool = internal_any_hook_bool_is_true<SupposedValueTraits>::value>
128 struct any_or_concrete_value_traits;
129 
130 //Base any hook
131 template<class T, class BaseHook>
132 struct get_base_value_traits<T, BaseHook, true>
133    : any_hook_base_value_traits<T, BaseHook>
134 {};
135 
136 //Non-any base hook
137 template<class T, class BaseHook>
138 struct get_base_value_traits<T, BaseHook, false>
139    : concrete_hook_base_value_traits<T, BaseHook>
140 {};
141 
142 //...It's a default hook
143 template<class SupposedValueTraits, class T>
144 struct supposed_value_traits<SupposedValueTraits, T, true>
145 {  typedef typename SupposedValueTraits::template apply<T>::type type;  };
146 
147 //...Not  a default hook
148 template<class SupposedValueTraits, class T>
149 struct supposed_value_traits<SupposedValueTraits, T, false>
150 {  typedef SupposedValueTraits type;   };
151 
152 //...It's a base hook
153 template<class BaseHook, class T>
154 struct supposed_base_value_traits<BaseHook, T, true>
155    : get_base_value_traits<T, BaseHook>
156 {};
157 
158 //...Not a base hook, try if it's a member or value_traits
159 template<class SupposedValueTraits, class T>
160 struct supposed_base_value_traits<SupposedValueTraits, T, false>
161    : supposed_member_value_traits<SupposedValueTraits>
162 {};
163 
164 //...It's a member hook
165 template<class MemberHook>
166 struct supposed_member_value_traits<MemberHook, true>
167    : get_member_value_traits<MemberHook>
168 {};
169 
170 //...Not a member hook
171 template<class SupposedValueTraits>
172 struct supposed_member_value_traits<SupposedValueTraits, false>
173    : any_or_concrete_value_traits<SupposedValueTraits>
174 {};
175 
176 template<class AnyToSomeHook_ProtoValueTraits>
177 struct any_or_concrete_value_traits<AnyToSomeHook_ProtoValueTraits, true>
178 {
179    //A hook node (non-base, e.g.: member or other value traits
180    typedef typename AnyToSomeHook_ProtoValueTraits::basic_hook_t        basic_hook_t;
181    typedef typename pointer_rebind
182       <typename basic_hook_t::node_ptr, void>::type                     void_pointer;
183    typedef typename AnyToSomeHook_ProtoValueTraits::template
184       node_traits_from_voidptr<void_pointer>::type                      any_node_traits;
185 
186    struct type : basic_hook_t
187    {
188       typedef any_node_traits node_traits;
189    };
190 };
191 
192 template<class SupposedValueTraits>
193 struct any_or_concrete_value_traits<SupposedValueTraits, false>
194 {
195    typedef SupposedValueTraits type;
196 };
197 
198 ////////////////////////////////////////
199 //  get_value_traits / get_node_traits
200 ////////////////////////////////////////
201 
202 template<class T, class SupposedValueTraits>
203 struct get_value_traits
204    : supposed_base_value_traits<typename supposed_value_traits<SupposedValueTraits, T>::type, T>
205 {};
206 
207 template<class SupposedValueTraits>
208 struct get_node_traits
209 {
210    typedef typename get_value_traits<void, SupposedValueTraits>::type::node_traits type;
211 };
212 
213 }  //namespace detail{
214 
215 #endif   //BOOST_INTRUSIVE_DOXYGEN_INVOKED
216 
217 }  //namespace intrusive {
218 }  //namespace boost {
219 
220 #include <boost/intrusive/detail/config_end.hpp>
221 
222 #endif   //#ifndef BOOST_INTRUSIVE_DETAIL_GET_VALUE_TRAITS_HPP
223