]> git.lyx.org Git - lyx.git/blob - boost/boost/type_traits/is_base_and_derived.hpp
update to boost 1.30.1
[lyx.git] / boost / boost / type_traits / is_base_and_derived.hpp
1
2 // (C) Copyright Rani Sharoni 2003.
3 // Permission to copy, use, modify, sell and distribute this software is 
4 // granted provided this copyright notice appears in all copies. This software 
5 // is provided "as is" without express or implied warranty, and with no claim 
6 // as to its suitability for any purpose.
7 //
8 // See http://www.boost.org for most recent version including documentation.
9
10 #ifndef BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
11 #define BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
12
13 #include "boost/type_traits/is_class.hpp"
14 #include "boost/type_traits/is_same.hpp"
15 #include "boost/type_traits/is_convertible.hpp"
16 #include "boost/type_traits/detail/ice_and.hpp"
17 #include "boost/type_traits/remove_cv.hpp"
18 #include "boost/config.hpp"
19
20 // should be the last #include
21 #include "boost/type_traits/detail/bool_trait_def.hpp"
22
23 namespace boost {
24
25 namespace detail {
26
27 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)) \
28  && !BOOST_WORKAROUND(__SUNPRO_CC , BOOST_TESTED_AT(0x540)) \
29  && !BOOST_WORKAROUND(__EDG_VERSION__, <= 243)
30                              // The EDG version number is a lower estimate.
31                              // It is not currently known which EDG version
32                              // exactly fixes the problem.
33
34 /*************************************************************************
35
36 This version detects ambiguous base classes and private base classes
37 correctly, and was devised by Rani Sharoni.
38
39 Explanation by Terje Slettebø and Rani Sharoni.
40
41 Let's take the multiple base class below as an example, and the following
42 will also show why there's not a problem with private or ambiguous base
43 class:
44
45 struct B {};
46 struct B1 : B {};
47 struct B2 : B {};
48 struct D : private B1, private B2 {};
49
50 is_base_and_derived<B, D>::value;
51
52 First, some terminology:
53
54 SC  - Standard conversion
55 UDC - User-defined conversion
56
57 A user-defined conversion sequence consists of an SC, followed by an UDC,
58 followed by another SC. Either SC may be the identity conversion.
59
60 When passing the default-constructed Host object to the overloaded check()
61 functions (initialization 8.5/14/4/3), we have several viable implicit
62 conversion sequences:
63
64 For "static no_type check(B const volatile *, int)" we have the conversion
65 sequences:
66
67 C -> C const (SC - Qualification Adjustment) -> B const volatile* (UDC)
68 C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
69      B const volatile* (SC - Conversion)
70
71 For "static yes_type check(D const volatile *, T)" we have the conversion
72 sequence:
73
74 C -> D const volatile* (UDC)
75
76 According to 13.3.3.1/4, in context of user-defined conversion only the
77 standard conversion sequence is considered when selecting the best viable
78 function, so it only considers up to the user-defined conversion. For the
79 first function this means choosing between C -> C const and C -> C, and it
80 chooses the latter, because it's a proper subset (13.3.3.2/3/2) of the
81 former. Therefore, we have:
82
83 C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
84      B const volatile* (SC - Conversion)
85 C -> D const volatile* (UDC)
86
87 Here, the principle of the "shortest subsequence" applies again, and it
88 chooses C -> D const volatile*. This shows that it doesn't even need to
89 consider the multiple paths to B, or accessibility, as that possibility is
90 eliminated before it could possibly cause ambiguity or access violation.
91
92 If D is not derived from B, it has to choose between C -> C const -> B const
93 volatile* for the first function, and C -> D const volatile* for the second
94 function, which are just as good (both requires a UDC, 13.3.3.2), had it not
95 been for the fact that "static no_type check(B const volatile *, int)" is
96 not templated, which makes C -> C const -> B const volatile* the best choice
97 (13.3.3/1/4), resulting in "no".
98
99 Also, if Host::operator B const volatile* hadn't been const, the two
100 conversion sequences for "static no_type check(B const volatile *, int)", in
101 the case where D is derived from B, would have been ambiguous.
102
103 See also
104 http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.
105 google.com and links therein.
106
107 *************************************************************************/
108
109 template <typename B, typename D>
110 struct bd_helper
111 {
112     template <typename T>
113     static type_traits::yes_type check(D const volatile *, T);
114     static type_traits::no_type  check(B const volatile *, int);
115 };
116
117 template<typename B, typename D>
118 struct is_base_and_derived_impl2
119 {
120     struct Host
121     {
122         operator B const volatile *() const;
123         operator D const volatile *();
124     };
125
126     BOOST_STATIC_CONSTANT(bool, value =
127         sizeof(bd_helper<B,D>::check(Host(), 0)) == sizeof(type_traits::yes_type));
128 };
129
130 #else
131
132 //
133 // broken version:
134 //
135 template<typename B, typename D>
136 struct is_base_and_derived_impl2
137 {
138     BOOST_STATIC_CONSTANT(bool, value =
139         (::boost::is_convertible<D*,B*>::value));
140 };
141
142 #define BOOST_BROKEN_IS_BASE_AND_DERIVED
143
144 #endif
145
146 template <typename B, typename D>
147 struct is_base_and_derived_impl3
148 {
149     BOOST_STATIC_CONSTANT(bool, value = false);
150 };
151
152 template <bool ic1, bool ic2, bool iss>
153 struct is_base_and_derived_select
154 {
155    template <class T, class U>
156    struct rebind
157    {
158       typedef is_base_and_derived_impl3<T,U> type;
159    };
160 };
161
162 template <>
163 struct is_base_and_derived_select<true,true,false>
164 {
165    template <class T, class U>
166    struct rebind
167    {
168       typedef is_base_and_derived_impl2<T,U> type;
169    };
170 };
171
172 template <typename B, typename D>
173 struct is_base_and_derived_impl
174 {
175     typedef typename remove_cv<B>::type ncvB;
176     typedef typename remove_cv<D>::type ncvD;
177
178     typedef is_base_and_derived_select<
179        ::boost::is_class<B>::value,
180        ::boost::is_class<D>::value,
181        ::boost::is_same<B,D>::value> selector;
182     typedef typename selector::template rebind<ncvB,ncvD> binder;
183     typedef typename binder::type bound_type;
184
185     BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
186 };
187
188 } // namespace detail
189
190 BOOST_TT_AUX_BOOL_TRAIT_DEF2(
191       is_base_and_derived
192     , Base
193     , Derived
194     , (::boost::detail::is_base_and_derived_impl<Base,Derived>::value)
195     )
196
197 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
198 BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC2_2(typename Base,typename Derived,is_base_and_derived,Base&,Derived,false)
199 BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC2_2(typename Base,typename Derived,is_base_and_derived,Base,Derived&,false)
200 BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC2_2(typename Base,typename Derived,is_base_and_derived,Base&,Derived&,false)
201 #endif
202
203 } // namespace boost
204
205 #include "boost/type_traits/detail/bool_trait_undef.hpp"
206
207 #endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED