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