Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2003-01-29 02:04:46


>From: "Terje Slettebø" <tslettebo_at_[hidden]>

> >From: "Rani Sharoni" <rani_sharoni_at_[hidden]>
>
> > Before changing the documentation please consider the following improved
> > implemetation that overcomes ambiguity and access control issues of the
> > current is_base_and_derived implemetation (I lately posted it to
> c.l.c++.m)
> > :
> >
> > template <typename B, typename D>
> > struct is_base_and_derived
> > {
> > private:
> > typedef char (&yes)[1];
> > typedef char (&no) [2];
> >
> > template<typename T>
> > static yes check(D const volatile &, T);
> > static no check(B const volatile &, int);
> >
> > struct C
> > {
> > operator B const volatile &() const;
> > operator D const volatile &();
> > };
> >
> > static C getC();
> > public:
> > static const bool result =
> > sizeof(check(getC(), 0)) == sizeof(yes);
> > };
> >
> > Additional specializations needed (e.g. void and reference types)
>
> Very nice, Rani. Very clever. :)
>
> It's interesting that, according to your clc++m posting, the inspiration
of
> this came from Andrei Alexandrescu's article on Mojo, who also came up
with
> Loki's SuperSubclass trait. Dave Abrahams is also credited in the thread,
> for contributing to the above technique.

The technique the above is based on is also very clever, of course. :)

> As I understand, the reason it works for multiple occurrences of the same
> base class is that it's not asking for D's B subobject, but instead for a
> conversion to _a_ B (any B).

After I sent this I came to wonder how this works, after all, and I found
that the actual conversion done is C to D, not D to B, but the end result is
that it means D is derived from B.

In the previous posting, I didn't want to repeat the explanation given in
the Vandevoorde posting that Rani gives link to in the clc++m posting
(http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting
.google.com). However, as Rani's code uses the technique there, with a few
twists, I thought it could be useful to give a better explanation of its
workings than my previous posting (which was mostly a sketch, to not repeat
the mentioned posting, but thanks for the acknowledgement, Dave A.). So here
goes:

Let's take the multiple base class mentioned above, as an example, and the
following will also show why there's not a problem with ambiguous base
class:

struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : B1, private B2 {};

typedef char Test[is_base_and_derived<B, D>::result]; // improvement 1 -
multiple base

We have several possible conversion sequences:

For "static no 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
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 -> B1/B2 -> B
C -> D

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. :)

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".

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.

Regards,

Terje


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk