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