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