1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/intrusive for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_INTRUSIVE_POINTER_REBIND_HPP
12#define BOOST_INTRUSIVE_POINTER_REBIND_HPP
13
14#ifndef BOOST_INTRUSIVE_DETAIL_WORKAROUND_HPP
15#include <boost/intrusive/detail/workaround.hpp>
16#endif //BOOST_INTRUSIVE_DETAIL_WORKAROUND_HPP
17
18#ifndef BOOST_CONFIG_HPP
19# include <boost/config.hpp>
20#endif
21
22#if defined(BOOST_HAS_PRAGMA_ONCE)
23# pragma once
24#endif
25
26namespace boost {
27namespace intrusive {
28
29///////////////////////////
30//struct pointer_rebind_mode
31///////////////////////////
32template <typename Ptr, typename U>
33struct pointer_has_rebind
34{
35 template <typename V> struct any
36 { any(const V&) { } };
37
38 template <typename X>
39 static char test(int, typename X::template rebind<U>*);
40
41 template <typename X>
42 static int test(any<int>, void*);
43
44 static const bool value = (1 == sizeof(test<Ptr>(0, 0)));
45};
46
47template <typename Ptr, typename U>
48struct pointer_has_rebind_other
49{
50 template <typename V> struct any
51 { any(const V&) { } };
52
53 template <typename X>
54 static char test(int, typename X::template rebind<U>::other*);
55
56 template <typename X>
57 static int test(any<int>, void*);
58
59 static const bool value = (1 == sizeof(test<Ptr>(0, 0)));
60};
61
62template <typename Ptr, typename U>
63struct pointer_rebind_mode
64{
65 static const unsigned int rebind = (unsigned int)pointer_has_rebind<Ptr, U>::value;
66 static const unsigned int rebind_other = (unsigned int)pointer_has_rebind_other<Ptr, U>::value;
67 static const unsigned int mode = rebind + rebind*rebind_other;
68};
69
70////////////////////////
71//struct pointer_rebinder
72////////////////////////
73template <typename Ptr, typename U, unsigned int RebindMode>
74struct pointer_rebinder;
75
76// Implementation of pointer_rebinder<U>::type if Ptr has
77// its own rebind<U>::other type (C++03)
78template <typename Ptr, typename U>
79struct pointer_rebinder< Ptr, U, 2u >
80{
81 typedef typename Ptr::template rebind<U>::other type;
82};
83
84// Implementation of pointer_rebinder<U>::type if Ptr has
85// its own rebind template.
86template <typename Ptr, typename U>
87struct pointer_rebinder< Ptr, U, 1u >
88{
89 typedef typename Ptr::template rebind<U> type;
90};
91
92// Specialization of pointer_rebinder if Ptr does not
93// have its own rebind template but has a the form Ptr<A, An...>,
94// where An... comprises zero or more type parameters.
95// Many types fit this form, hence many pointers will get a
96// reasonable default for rebind.
97#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
98
99template <template <class, class...> class Ptr, typename A, class... An, class U>
100struct pointer_rebinder<Ptr<A, An...>, U, 0u >
101{
102 typedef Ptr<U, An...> type;
103};
104
105//Needed for non-conforming compilers like GCC 4.3
106template <template <class> class Ptr, typename A, class U>
107struct pointer_rebinder<Ptr<A>, U, 0u >
108{
109 typedef Ptr<U> type;
110};
111
112#else //C++03 compilers
113
114template <template <class> class Ptr //0arg
115 , typename A
116 , class U>
117struct pointer_rebinder<Ptr<A>, U, 0u>
118{ typedef Ptr<U> type; };
119
120template <template <class, class> class Ptr //1arg
121 , typename A, class P0
122 , class U>
123struct pointer_rebinder<Ptr<A, P0>, U, 0u>
124{ typedef Ptr<U, P0> type; };
125
126template <template <class, class, class> class Ptr //2arg
127 , typename A, class P0, class P1
128 , class U>
129struct pointer_rebinder<Ptr<A, P0, P1>, U, 0u>
130{ typedef Ptr<U, P0, P1> type; };
131
132template <template <class, class, class, class> class Ptr //3arg
133 , typename A, class P0, class P1, class P2
134 , class U>
135struct pointer_rebinder<Ptr<A, P0, P1, P2>, U, 0u>
136{ typedef Ptr<U, P0, P1, P2> type; };
137
138template <template <class, class, class, class, class> class Ptr //4arg
139 , typename A, class P0, class P1, class P2, class P3
140 , class U>
141struct pointer_rebinder<Ptr<A, P0, P1, P2, P3>, U, 0u>
142{ typedef Ptr<U, P0, P1, P2, P3> type; };
143
144template <template <class, class, class, class, class, class> class Ptr //5arg
145 , typename A, class P0, class P1, class P2, class P3, class P4
146 , class U>
147struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4>, U, 0u>
148{ typedef Ptr<U, P0, P1, P2, P3, P4> type; };
149
150template <template <class, class, class, class, class, class, class> class Ptr //6arg
151 , typename A, class P0, class P1, class P2, class P3, class P4, class P5
152 , class U>
153struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4, P5>, U, 0u>
154{ typedef Ptr<U, P0, P1, P2, P3, P4, P5> type; };
155
156template <template <class, class, class, class, class, class, class, class> class Ptr //7arg
157 , typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
158 , class U>
159struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4, P5, P6>, U, 0u>
160{ typedef Ptr<U, P0, P1, P2, P3, P4, P5, P6> type; };
161
162template <template <class, class, class, class, class, class, class, class, class> class Ptr //8arg
163 , typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
164 , class U>
165struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4, P5, P6, P7>, U, 0u>
166{ typedef Ptr<U, P0, P1, P2, P3, P4, P5, P6, P7> type; };
167
168template <template <class, class, class, class, class, class, class, class, class, class> class Ptr //9arg
169 , typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
170 , class U>
171struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U, 0u>
172{ typedef Ptr<U, P0, P1, P2, P3, P4, P5, P6, P7, P8> type; };
173
174#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
175
176template <typename Ptr, typename U>
177struct pointer_rebind
178 : public pointer_rebinder<Ptr, U, pointer_rebind_mode<Ptr, U>::mode>
179{};
180
181template <typename T, typename U>
182struct pointer_rebind<T*, U>
183{ typedef U* type; };
184
185} //namespace container {
186} //namespace boost {
187
188#endif // defined(BOOST_INTRUSIVE_POINTER_REBIND_HPP)
189