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).
7 // See http://www.boost.org/libs/type_traits for most recent version including documentation.
9 #ifndef BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
10 #define BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
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"
19 // should be the last #include
20 #include "boost/type_traits/detail/bool_trait_def.hpp"
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))
31 // The EDG version number is a lower estimate.
32 // It is not currently known which EDG version
33 // exactly fixes the problem.
35 /*************************************************************************
37 This version detects ambiguous base classes and private base classes
38 correctly, and was devised by Rani Sharoni.
40 Explanation by Terje Slettebø and Rani Sharoni.
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
49 struct D : private B1, private B2 {};
51 is_base_and_derived<B, D>::value;
53 First, some terminology:
55 SC - Standard conversion
56 UDC - User-defined conversion
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.
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
65 For "static no_type check_sig(B const volatile *, int)" we have the conversion
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)
72 For "static yes_type check_sig(D const volatile *, T)" we have the conversion
75 C -> D const volatile* (UDC)
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:
84 C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
85 B const volatile* (SC - Conversion)
86 C -> D const volatile* (UDC)
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.
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".
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.
105 http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.
106 google.com and links therein.
108 *************************************************************************/
110 template <typename B, typename D>
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);
118 template<typename B, typename D>
119 struct is_base_and_derived_impl2
123 operator B const volatile *() const;
124 operator D const volatile *();
127 BOOST_STATIC_CONSTANT(bool, value =
128 sizeof(bd_helper<B,D>::check_sig(Host(), 0)) == sizeof(type_traits::yes_type));
136 template<typename B, typename D>
137 struct is_base_and_derived_impl2
139 BOOST_STATIC_CONSTANT(bool, value =
140 (::boost::is_convertible<D*,B*>::value));
143 #define BOOST_BROKEN_IS_BASE_AND_DERIVED
147 template <typename B, typename D>
148 struct is_base_and_derived_impl3
150 BOOST_STATIC_CONSTANT(bool, value = false);
153 template <bool ic1, bool ic2, bool iss>
154 struct is_base_and_derived_select
156 template <class T, class U>
159 typedef is_base_and_derived_impl3<T,U> type;
164 struct is_base_and_derived_select<true,true,false>
166 template <class T, class U>
169 typedef is_base_and_derived_impl2<T,U> type;
173 template <typename B, typename D>
174 struct is_base_and_derived_impl
176 typedef typename remove_cv<B>::type ncvB;
177 typedef typename remove_cv<D>::type ncvD;
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;
186 BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
189 } // namespace detail
191 BOOST_TT_AUX_BOOL_TRAIT_DEF2(
195 , (::boost::detail::is_base_and_derived_impl<Base,Derived>::value)
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)
206 #include "boost/type_traits/detail/bool_trait_undef.hpp"
208 #endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED