forked from boostorg/type_traits
Updated description
[SVN r17898]
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
|
||||
// (C) Copyright Rani Sharoni 2002.
|
||||
// (C) Copyright Rani Sharoni 2003.
|
||||
// Permission to copy, use, modify, sell and distribute this software is
|
||||
// granted provided this copyright notice appears in all copies. This software
|
||||
// is provided "as is" without express or implied warranty, and with no claim
|
||||
@ -35,58 +35,73 @@ namespace detail {
|
||||
This version detects ambiguous base classes and private base classes
|
||||
correctly, and was devised by Rani Sharoni.
|
||||
|
||||
The following explanation is by Terje Slettebo:
|
||||
Explanation by Terje Sletteb<EFBFBD> and Rani Sharoni.
|
||||
|
||||
Let's take the multiple base class below as an example, and the
|
||||
following will also show why there's not a problem with ambiguous base
|
||||
Let's take the multiple base class below as an example, and the following
|
||||
will also show why there's not a problem with private or ambiguous base
|
||||
class:
|
||||
|
||||
struct B {};
|
||||
struct B1 : B {};
|
||||
struct B2 : B {};
|
||||
struct D : B1, private B2 {};
|
||||
struct D : private B1, private B2 {};
|
||||
|
||||
typedef char Test[is_base_and_derived<B, D>::result]; // improvement 1 -
|
||||
multiple base
|
||||
is_base_and_derived<B, D>::value;
|
||||
|
||||
First, some terminology:
|
||||
|
||||
We have several possible conversion sequences:
|
||||
SC - Standard conversion
|
||||
UDC - User-defined conversion
|
||||
|
||||
For "static no check(B const volatile *, int)" we have the conversion
|
||||
A user-defined conversion sequence consists of an SC, followed by an UDC,
|
||||
followed by another SC. Either SC may be the identity conversion.
|
||||
|
||||
When passing the default-constructed Host object to the overloaded check()
|
||||
functions (initialization 8.5/14/4/3), we have several viable implicit
|
||||
conversion sequences:
|
||||
|
||||
For "static no_type check(B const volatile *, int)" we have the conversion
|
||||
sequences:
|
||||
C -> C const -> B*
|
||||
and
|
||||
C -> D* -> B1*|B2* -> B*
|
||||
|
||||
For "static yes check(D const volatile *, T)" we have the conversion
|
||||
C -> C const (SC - Qualification Adjustment) -> B const volatile* (UDC)
|
||||
C -> D const volatile* (UDC) -> B1 const volatile*/B2 const volatile* ->
|
||||
B const volatile* (SC - Conversion)
|
||||
|
||||
For "static yes_type check(D const volatile *, T)" we have the conversion
|
||||
sequence:
|
||||
C -> D*
|
||||
|
||||
Since, for the purpose of selecting the appropriate user-defined conversion
|
||||
for a given function, it only considers up to the user-defined conversion,
|
||||
for the first function this means choosing between C -> C const and C -> C,
|
||||
and it chooses the latter. Therefore, we have:
|
||||
C -> D const volatile* (UDC)
|
||||
|
||||
C -> D* -> B1*|B2* -> B*
|
||||
C -> D*
|
||||
According to 13.3.3.1/4, in context of user-defined conversion only the
|
||||
standard conversion sequence is considered when selecting the best viable
|
||||
function, so it only considers up to the user-defined conversion. For the
|
||||
first function this means choosing between C -> C const and C -> C, and it
|
||||
chooses the latter, because it's a proper subset (13.3.3.2/3/2) of the
|
||||
former. Therefore, we have:
|
||||
|
||||
Here, the principle of the "shortest subsequence" applies, and it chooses
|
||||
C -> D*. This shows that it doesn't even need to consider the multiple paths
|
||||
to B, as that possibility is eliminated before it could possibly cause
|
||||
ambiguity. Nifty. :)
|
||||
C -> D const volatile* (UDC) -> B1 const volatile*/B2 const volatile* ->
|
||||
B const volatile* (SC - Conversion)
|
||||
C -> D const volatile* (UDC)
|
||||
|
||||
As Daveed notes in the posting Rani gives a link to in the clc++m posting,
|
||||
if D is not derived from B, it has to choose between C -> C const -> B* for
|
||||
the first function, and C -> D* for the second function, which are just as
|
||||
good, _had it not been for the fact that "static no check(B const volatile
|
||||
&, int)" is not templated (as Rani points out in the posting)_, which makes
|
||||
C -> C const -> B* the best choice, resulting in "no".
|
||||
Here, the principle of the "shortest subsequence" applies again, and it
|
||||
chooses C -> D const volatile*. This shows that it doesn't even need to
|
||||
consider the multiple paths to B, or accessibility, as that possibility is
|
||||
eliminated before it could possibly cause ambiguity or access violation.
|
||||
|
||||
Also, if C::operator B* hadn't been const, the two conversion sequences for
|
||||
"static no check(B const volatile *, int)" would have been ambiguous.
|
||||
If D is not derived from B, it has to choose between C -> C const -> B const
|
||||
volatile* for the first function, and C -> D const volatile* for the second
|
||||
function, which are just as good (both requires a UDC, 13.3.3.2), had it not
|
||||
been for the fact that "static no_type check(B const volatile *, int)" is
|
||||
not templated, which makes C -> C const -> B const volatile* the best choice
|
||||
(13.3.3/1/4), resulting in "no".
|
||||
|
||||
See also http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.google.com
|
||||
and links therein.
|
||||
Also, if Host::operator B const volatile* hadn't been const, the two
|
||||
conversion sequences for "static no_type check(B const volatile *, int)", in
|
||||
the case where D is derived from B, would have been ambiguous.
|
||||
|
||||
See also
|
||||
http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.
|
||||
google.com and links therein.
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
@ -189,5 +204,3 @@ BOOST_TT_AUX_BOOL_TRAIT_PARTIAL_SPEC2_2(typename Base,typename Derived,is_base_a
|
||||
#include "boost/type_traits/detail/bool_trait_undef.hpp"
|
||||
|
||||
#endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user