1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga  2006-2013
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_ANY_HOOK_HPP
14 #define BOOST_INTRUSIVE_ANY_HOOK_HPP
15 
16 #include <boost/intrusive/detail/config_begin.hpp>
17 #include <boost/intrusive/intrusive_fwd.hpp>
18 #include <boost/intrusive/detail/any_node_and_algorithms.hpp>
19 #include <boost/intrusive/options.hpp>
20 #include <boost/intrusive/detail/generic_hook.hpp>
21 #include <boost/intrusive/detail/mpl.hpp>
22 #include <boost/intrusive/pointer_rebind.hpp>
23 
24 #if defined(BOOST_HAS_PRAGMA_ONCE)
25 #  pragma once
26 #endif
27 
28 namespace boost {
29 namespace intrusive {
30 
31 //! Helper metafunction to define a \c \c any_base_hook that yields to the same
32 //! type when the same options (either explicitly or implicitly) are used.
33 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
34 template<class ...Options>
35 #else
36 template<class O1 = void, class O2 = void, class O3 = void>
37 #endif
38 struct make_any_base_hook
39 {
40    /// @cond
41    typedef typename pack_options
42       < hook_defaults,
43       #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
44       O1, O2, O3
45       #else
46       Options...
47       #endif
48       >::type packed_options;
49 
50    typedef generic_hook
51    < any_algorithms<typename packed_options::void_pointer>
52    , typename packed_options::tag
53    , packed_options::link_mode
54    , AnyBaseHookId
55    > implementation_defined;
56    /// @endcond
57    typedef implementation_defined type;
58 };
59 
60 //! Derive a class from this hook in order to store objects of that class
61 //! in an intrusive container.
62 //!
63 //! The hook admits the following options: \c tag<>, \c void_pointer<> and
64 //! \c link_mode<>.
65 //!
66 //! \c tag<> defines a tag to identify the node.
67 //! The same tag value can be used in different classes, but if a class is
68 //! derived from more than one \c any_base_hook, then each \c any_base_hook needs its
69 //! unique tag.
70 //!
71 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link).
72 //!
73 //! \c void_pointer<> is the pointer type that will be used internally in the hook
74 //! and the container configured to use this hook.
75 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
76 template<class ...Options>
77 #else
78 template<class O1, class O2, class O3>
79 #endif
80 class any_base_hook
81    :  public make_any_base_hook
82       #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
83       <O1, O2, O3>
84       #else
85       <Options...>
86       #endif
87       ::type
88 {
89    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
90    public:
91    //! <b>Effects</b>: If link_mode is or \c safe_link
92    //!   initializes the node to an unlinked state.
93    //!
94    //! <b>Throws</b>: Nothing.
95    any_base_hook();
96 
97    //! <b>Effects</b>: If link_mode is or \c safe_link
98    //!   initializes the node to an unlinked state. The argument is ignored.
99    //!
100    //! <b>Throws</b>: Nothing.
101    //!
102    //! <b>Rationale</b>: Providing a copy-constructor
103    //!   makes classes using the hook STL-compliant without forcing the
104    //!   user to do some additional work. \c swap can be used to emulate
105    //!   move-semantics.
106    any_base_hook(const any_base_hook& );
107 
108    //! <b>Effects</b>: Empty function. The argument is ignored.
109    //!
110    //! <b>Throws</b>: Nothing.
111    //!
112    //! <b>Rationale</b>: Providing an assignment operator
113    //!   makes classes using the hook STL-compliant without forcing the
114    //!   user to do some additional work. \c swap can be used to emulate
115    //!   move-semantics.
116    any_base_hook& operator=(const any_base_hook& );
117 
118    //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
119    //!   nothing (ie. no code is generated). If link_mode is \c safe_link and the
120    //!   object is stored in a container an assertion is raised.
121    //!
122    //! <b>Throws</b>: Nothing.
123    ~any_base_hook();
124 
125    //! <b>Precondition</b>: link_mode must be \c safe_link.
126    //!
127    //! <b>Returns</b>: true, if the node belongs to a container, false
128    //!   otherwise. This function can be used to test whether \c container::iterator_to
129    //!   will return a valid iterator.
130    //!
131    //! <b>Complexity</b>: Constant
132    bool is_linked() const;
133    #endif
134 };
135 
136 //! Helper metafunction to define a \c \c any_member_hook that yields to the same
137 //! type when the same options (either explicitly or implicitly) are used.
138 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
139 template<class ...Options>
140 #else
141 template<class O1 = void, class O2 = void, class O3 = void>
142 #endif
143 struct make_any_member_hook
144 {
145    /// @cond
146    typedef typename pack_options
147       < hook_defaults,
148       #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
149       O1, O2, O3
150       #else
151       Options...
152       #endif
153       >::type packed_options;
154 
155    typedef generic_hook
156    < any_algorithms<typename packed_options::void_pointer>
157    , member_tag
158    , packed_options::link_mode
159    , NoBaseHookId
160    > implementation_defined;
161    /// @endcond
162    typedef implementation_defined type;
163 };
164 
165 //! Store this hook in a class to be inserted
166 //! in an intrusive container.
167 //!
168 //! The hook admits the following options: \c void_pointer<> and
169 //! \c link_mode<>.
170 //!
171 //! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link).
172 //!
173 //! \c void_pointer<> is the pointer type that will be used internally in the hook
174 //! and the container configured to use this hook.
175 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
176 template<class ...Options>
177 #else
178 template<class O1, class O2, class O3>
179 #endif
180 class any_member_hook
181    :  public make_any_member_hook
182       #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
183       <O1, O2, O3>
184       #else
185       <Options...>
186       #endif
187       ::type
188 {
189    #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
190    public:
191    //! <b>Effects</b>: If link_mode is or \c safe_link
192    //!   initializes the node to an unlinked state.
193    //!
194    //! <b>Throws</b>: Nothing.
195    any_member_hook();
196 
197    //! <b>Effects</b>: If link_mode is or \c safe_link
198    //!   initializes the node to an unlinked state. The argument is ignored.
199    //!
200    //! <b>Throws</b>: Nothing.
201    //!
202    //! <b>Rationale</b>: Providing a copy-constructor
203    //!   makes classes using the hook STL-compliant without forcing the
204    //!   user to do some additional work. \c swap can be used to emulate
205    //!   move-semantics.
206    any_member_hook(const any_member_hook& );
207 
208    //! <b>Effects</b>: Empty function. The argument is ignored.
209    //!
210    //! <b>Throws</b>: Nothing.
211    //!
212    //! <b>Rationale</b>: Providing an assignment operator
213    //!   makes classes using the hook STL-compliant without forcing the
214    //!   user to do some additional work. \c swap can be used to emulate
215    //!   move-semantics.
216    any_member_hook& operator=(const any_member_hook& );
217 
218    //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does
219    //!   nothing (ie. no code is generated). If link_mode is \c safe_link and the
220    //!   object is stored in a container an assertion is raised.
221    //!
222    //! <b>Throws</b>: Nothing.
223    ~any_member_hook();
224 
225    //! <b>Precondition</b>: link_mode must be \c safe_link.
226    //!
227    //! <b>Returns</b>: true, if the node belongs to a container, false
228    //!   otherwise. This function can be used to test whether \c container::iterator_to
229    //!   will return a valid iterator.
230    //!
231    //! <b>Complexity</b>: Constant
232    bool is_linked() const;
233    #endif
234 };
235 
236 /// @cond
237 
238 namespace detail{
239 
240 BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(old_proto_value_traits_base_hook, hooktags::is_base_hook)
241 
242 //!This option setter specifies that the container
243 //!must use the specified base hook
244 template<class BasicHook, template <class> class NodeTraits>
245 struct any_to_some_hook
246 {
247    typedef typename BasicHook::template pack<empty>::proto_value_traits old_proto_value_traits;
248 
249    template<class Base>
250    struct pack : public Base
251    {
252       struct proto_value_traits
253       {
254          //proto_value_traits::hooktags::is_base_hook is used by get_value_traits
255          //to detect base hooks, so mark it in case BasicHook has it.
256          struct hooktags
257          {
258             static const bool is_base_hook = old_proto_value_traits_base_hook_bool_is_true
259                <old_proto_value_traits>::value;
260          };
261 
262          typedef old_proto_value_traits basic_hook_t;
263          static const bool is_any_hook = true;
264 
265          template<class VoidPtr>
266          struct node_traits_from_voidptr
267          {  typedef NodeTraits<VoidPtr> type;  };
268       };
269    };
270 };
271 
272 }  //namespace detail{
273 
274 /// @endcond
275 
276 //!This option setter specifies that
277 //!any hook should behave as an slist hook
278 template<class BasicHook>
279 struct any_to_slist_hook
280 /// @cond
281    :  public detail::any_to_some_hook<BasicHook, any_slist_node_traits>
282 /// @endcond
283 {};
284 
285 //!This option setter specifies that
286 //!any hook should behave as an list hook
287 template<class BasicHook>
288 struct any_to_list_hook
289 /// @cond
290    :  public detail::any_to_some_hook<BasicHook, any_list_node_traits>
291 /// @endcond
292 {};
293 
294 //!This option setter specifies that
295 //!any hook should behave as a set hook
296 template<class BasicHook>
297 struct any_to_set_hook
298 /// @cond
299    :  public detail::any_to_some_hook<BasicHook, any_rbtree_node_traits>
300 /// @endcond
301 {};
302 
303 //!This option setter specifies that
304 //!any hook should behave as an avl_set hook
305 template<class BasicHook>
306 struct any_to_avl_set_hook
307 /// @cond
308    :  public detail::any_to_some_hook<BasicHook, any_avltree_node_traits>
309 /// @endcond
310 {};
311 
312 //!This option setter specifies that any
313 //!hook should behave as a bs_set hook
314 template<class BasicHook>
315 struct any_to_bs_set_hook
316 /// @cond
317    :  public detail::any_to_some_hook<BasicHook, any_tree_node_traits>
318 /// @endcond
319 {};
320 
321 //!This option setter specifies that any hook
322 //!should behave as an unordered set hook
323 template<class BasicHook>
324 struct any_to_unordered_set_hook
325 /// @cond
326    :  public detail::any_to_some_hook<BasicHook, any_unordered_node_traits>
327 /// @endcond
328 {};
329 
330 
331 } //namespace intrusive
332 } //namespace boost
333 
334 #include <boost/intrusive/detail/config_end.hpp>
335 
336 #endif //BOOST_INTRUSIVE_ANY_HOOK_HPP
337