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 
26 namespace boost {
27 namespace intrusive {
28 
29 ///////////////////////////
30 //struct pointer_rebind_mode
31 ///////////////////////////
32 template <typename Ptr, typename U>
33 struct pointer_has_rebind
34 {
35    template <typename V> struct any
anyboost::intrusive::pointer_has_rebind::any36    {  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 
47 template <typename Ptr, typename U>
48 struct pointer_has_rebind_other
49 {
50    template <typename V> struct any
anyboost::intrusive::pointer_has_rebind_other::any51    {  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 
62 template <typename Ptr, typename U>
63 struct 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 ////////////////////////
73 template <typename Ptr, typename U, unsigned int RebindMode>
74 struct pointer_rebinder;
75 
76 // Implementation of pointer_rebinder<U>::type if Ptr has
77 // its own rebind<U>::other type (C++03)
78 template <typename Ptr, typename U>
79 struct 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.
86 template <typename Ptr, typename U>
87 struct 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 
99 template <template <class, class...> class Ptr, typename A, class... An, class U>
100 struct 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
106 template <template <class> class Ptr, typename A, class U>
107 struct pointer_rebinder<Ptr<A>, U, 0u >
108 {
109    typedef Ptr<U> type;
110 };
111 
112 #else //C++03 compilers
113 
114 template <template <class> class Ptr  //0arg
115          , typename A
116          , class U>
117 struct pointer_rebinder<Ptr<A>, U, 0u>
118 {  typedef Ptr<U> type;   };
119 
120 template <template <class, class> class Ptr  //1arg
121          , typename A, class P0
122          , class U>
123 struct pointer_rebinder<Ptr<A, P0>, U, 0u>
124 {  typedef Ptr<U, P0> type;   };
125 
126 template <template <class, class, class> class Ptr  //2arg
127          , typename A, class P0, class P1
128          , class U>
129 struct pointer_rebinder<Ptr<A, P0, P1>, U, 0u>
130 {  typedef Ptr<U, P0, P1> type;   };
131 
132 template <template <class, class, class, class> class Ptr  //3arg
133          , typename A, class P0, class P1, class P2
134          , class U>
135 struct pointer_rebinder<Ptr<A, P0, P1, P2>, U, 0u>
136 {  typedef Ptr<U, P0, P1, P2> type;   };
137 
138 template <template <class, class, class, class, class> class Ptr  //4arg
139          , typename A, class P0, class P1, class P2, class P3
140          , class U>
141 struct pointer_rebinder<Ptr<A, P0, P1, P2, P3>, U, 0u>
142 {  typedef Ptr<U, P0, P1, P2, P3> type;   };
143 
144 template <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>
147 struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4>, U, 0u>
148 {  typedef Ptr<U, P0, P1, P2, P3, P4> type;   };
149 
150 template <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>
153 struct pointer_rebinder<Ptr<A, P0, P1, P2, P3, P4, P5>, U, 0u>
154 {  typedef Ptr<U, P0, P1, P2, P3, P4, P5> type;   };
155 
156 template <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>
159 struct 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 
162 template <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>
165 struct 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 
168 template <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>
171 struct 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 
176 template <typename Ptr, typename U>
177 struct pointer_rebind
178    : public pointer_rebinder<Ptr, U, pointer_rebind_mode<Ptr, U>::mode>
179 {};
180 
181 template <typename T, typename U>
182 struct 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