]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_traits/include/boost/type_traits/is_base_and_derived.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / type_traits / include / boost / type_traits / is_base_and_derived.hpp
1
2 // (C) Copyright Rani Sharoni 2003.
3 // Use, modification and distribution are subject to the Boost Software License,
4 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt).
6 //
7 // See http://www.boost.org/libs/type_traits for most recent version including documentation.
8
9 #ifndef BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
10 #define BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
11
12 #include <boost/type_traits/intrinsics.hpp>
13 #include <boost/type_traits/integral_constant.hpp>
14 #ifndef BOOST_IS_BASE_OF
15 #include <boost/type_traits/is_class.hpp>
16 #include <boost/type_traits/is_same.hpp>
17 #include <boost/type_traits/is_convertible.hpp>
18 #include <boost/config.hpp>
19 #include <boost/static_assert.hpp>
20 #endif
21 #include <boost/type_traits/remove_cv.hpp>
22 #include <boost/type_traits/is_same.hpp>
23
24 namespace boost {
25
26 namespace detail {
27
28 #ifndef BOOST_IS_BASE_OF
29 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) \
30 && !BOOST_WORKAROUND(__SUNPRO_CC , <= 0x540) \
31 && !BOOST_WORKAROUND(__EDG_VERSION__, <= 243) \
32 && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
33
34 // The EDG version number is a lower estimate.
35 // It is not currently known which EDG version
36 // exactly fixes the problem.
37
38 /*************************************************************************
39
40 This version detects ambiguous base classes and private base classes
41 correctly, and was devised by Rani Sharoni.
42
43 Explanation by Terje Slettebo and Rani Sharoni.
44
45 Let's take the multiple base class below as an example, and the following
46 will also show why there's not a problem with private or ambiguous base
47 class:
48
49 struct B {};
50 struct B1 : B {};
51 struct B2 : B {};
52 struct D : private B1, private B2 {};
53
54 is_base_and_derived<B, D>::value;
55
56 First, some terminology:
57
58 SC - Standard conversion
59 UDC - User-defined conversion
60
61 A user-defined conversion sequence consists of an SC, followed by an UDC,
62 followed by another SC. Either SC may be the identity conversion.
63
64 When passing the default-constructed Host object to the overloaded check_sig()
65 functions (initialization 8.5/14/4/3), we have several viable implicit
66 conversion sequences:
67
68 For "static no_type check_sig(B const volatile *, int)" we have the conversion
69 sequences:
70
71 C -> C const (SC - Qualification Adjustment) -> B const volatile* (UDC)
72 C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
73 B const volatile* (SC - Conversion)
74
75 For "static yes_type check_sig(D const volatile *, T)" we have the conversion
76 sequence:
77
78 C -> D const volatile* (UDC)
79
80 According to 13.3.3.1/4, in context of user-defined conversion only the
81 standard conversion sequence is considered when selecting the best viable
82 function, so it only considers up to the user-defined conversion. For the
83 first function this means choosing between C -> C const and C -> C, and it
84 chooses the latter, because it's a proper subset (13.3.3.2/3/2) of the
85 former. Therefore, we have:
86
87 C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
88 B const volatile* (SC - Conversion)
89 C -> D const volatile* (UDC)
90
91 Here, the principle of the "shortest subsequence" applies again, and it
92 chooses C -> D const volatile*. This shows that it doesn't even need to
93 consider the multiple paths to B, or accessibility, as that possibility is
94 eliminated before it could possibly cause ambiguity or access violation.
95
96 If D is not derived from B, it has to choose between C -> C const -> B const
97 volatile* for the first function, and C -> D const volatile* for the second
98 function, which are just as good (both requires a UDC, 13.3.3.2), had it not
99 been for the fact that "static no_type check_sig(B const volatile *, int)" is
100 not templated, which makes C -> C const -> B const volatile* the best choice
101 (13.3.3/1/4), resulting in "no".
102
103 Also, if Host::operator B const volatile* hadn't been const, the two
104 conversion sequences for "static no_type check_sig(B const volatile *, int)", in
105 the case where D is derived from B, would have been ambiguous.
106
107 See also
108 http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.
109 google.com and links therein.
110
111 *************************************************************************/
112
113 template <typename B, typename D>
114 struct bd_helper
115 {
116 //
117 // This VC7.1 specific workaround stops the compiler from generating
118 // an internal compiler error when compiling with /vmg (thanks to
119 // Aleksey Gurtovoy for figuring out the workaround).
120 //
121 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
122 template <typename T>
123 static type_traits::yes_type check_sig(D const volatile *, T);
124 static type_traits::no_type check_sig(B const volatile *, int);
125 #else
126 static type_traits::yes_type check_sig(D const volatile *, long);
127 static type_traits::no_type check_sig(B const volatile * const&, int);
128 #endif
129 };
130
131 template<typename B, typename D>
132 struct is_base_and_derived_impl2
133 {
134 #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
135 #pragma warning(push)
136 #pragma warning(disable:6334)
137 #endif
138 //
139 // May silently do the wrong thing with incomplete types
140 // unless we trap them here:
141 //
142 BOOST_STATIC_ASSERT(sizeof(B) != 0);
143 BOOST_STATIC_ASSERT(sizeof(D) != 0);
144
145 struct Host
146 {
147 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
148 operator B const volatile *() const;
149 #else
150 operator B const volatile * const&() const;
151 #endif
152 operator D const volatile *();
153 };
154
155 BOOST_STATIC_CONSTANT(bool, value =
156 sizeof(bd_helper<B,D>::check_sig(Host(), 0)) == sizeof(type_traits::yes_type));
157 #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
158 #pragma warning(pop)
159 #endif
160 };
161
162 #else
163
164 //
165 // broken version:
166 //
167 template<typename B, typename D>
168 struct is_base_and_derived_impl2
169 {
170 BOOST_STATIC_CONSTANT(bool, value =
171 (::boost::is_convertible<D*,B*>::value));
172 };
173
174 #define BOOST_BROKEN_IS_BASE_AND_DERIVED
175
176 #endif
177
178 template <typename B, typename D>
179 struct is_base_and_derived_impl3
180 {
181 BOOST_STATIC_CONSTANT(bool, value = false);
182 };
183
184 template <bool ic1, bool ic2, bool iss>
185 struct is_base_and_derived_select
186 {
187 template <class T, class U>
188 struct rebind
189 {
190 typedef is_base_and_derived_impl3<T,U> type;
191 };
192 };
193
194 template <>
195 struct is_base_and_derived_select<true,true,false>
196 {
197 template <class T, class U>
198 struct rebind
199 {
200 typedef is_base_and_derived_impl2<T,U> type;
201 };
202 };
203
204 template <typename B, typename D>
205 struct is_base_and_derived_impl
206 {
207 typedef typename remove_cv<B>::type ncvB;
208 typedef typename remove_cv<D>::type ncvD;
209
210 typedef is_base_and_derived_select<
211 ::boost::is_class<B>::value,
212 ::boost::is_class<D>::value,
213 ::boost::is_same<ncvB,ncvD>::value> selector;
214 typedef typename selector::template rebind<ncvB,ncvD> binder;
215 typedef typename binder::type bound_type;
216
217 BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
218 };
219 #else
220 template <typename B, typename D>
221 struct is_base_and_derived_impl
222 {
223 typedef typename remove_cv<B>::type ncvB;
224 typedef typename remove_cv<D>::type ncvD;
225
226 BOOST_STATIC_CONSTANT(bool, value = (BOOST_IS_BASE_OF(B,D) && ! ::boost::is_same<ncvB,ncvD>::value));
227 };
228 #endif
229 } // namespace detail
230
231 template <class Base, class Derived> struct is_base_and_derived
232 : public integral_constant<bool, (::boost::detail::is_base_and_derived_impl<Base, Derived>::value)> {};
233
234 template <class Base, class Derived> struct is_base_and_derived<Base&, Derived> : public false_type{};
235 template <class Base, class Derived> struct is_base_and_derived<Base, Derived&> : public false_type{};
236 template <class Base, class Derived> struct is_base_and_derived<Base&, Derived&> : public false_type{};
237
238 #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
239 template <class Base> struct is_base_and_derived<Base, Base> : public true_type{};
240 #endif
241
242 } // namespace boost
243
244 #endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED