Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2003-01-31 10:15:49


>From: "Gennaro Prota" <gennaro_prota_at_[hidden]>

> On Thu, 30 Jan 2003 15:13:19 +0100, Terje Slettebø
> <tslettebo_at_[hidden]> wrote:
>
> [...]
> >> Roughly speaking B is a base of D if and only if
> >> the base-specifier-list of D contains a class name for B or for a
> >> class of which B is a base. Of course you can see if that's the case
> >> by knowing the definition of D and examining an inheritance graph. And
> >> since that's what a compiler does all the time, is_base_and_derived is
> >> another thing that could be (ahehm) easily implemented as a built-in
> >> operator.
> >
> >True. But it's also detectable using C++98, as shown by Rani's proposal.
>
> One must be *extremely careful* when making such an assertion.

In the following part of the posting, I said that if it turns out it doesn't
work correctly, then...

> We may
> "understand" how it works and have a few test cases, but that's not a
> big guarantee. C++ is a _very_ complex language, and all sorts of
> conversions can appear wherever you expect them the less. The fact
> that we don't see any leak in Rani's code doesn't mean that it there
> isn't. Probably, a week ago we were all "enough convinced" that it
> wasn't possible to detect a private base without causing an access
> error.

No. You can't prove a negative, an impossibility. You can't prove that
something can't be done. You can, however, prove that something can be done.
You use an analogy later here, and I can come with one, as well: No matter
how many black crows you find, you can't prove that there can never be a
white crow. Only one white crow is enough to prove that there can be a white
crow.

> And if we were convinced about that and were wrong, then we
> could be wrong now by thinking that the code works.

Like I said, I've never said that this has been _proven_. You seem to be
jumping the gun a little, here. Like I said in the posting, I'm not arguing
whether or not there should be built-in language support for this. I've just
pointed out some consequences of either approach.

> Let me make a little digression: the great Adrien Marie Legendre once
> "proved" that there doesn't exist any couple of rational numbers x and
> y such that:
>
> x**3 + y**3 = 6
>
> It then happened that Henry Ernest Dudeney published a solution with
> only two digits in the numerator and the denominator of both
> fractions:
>
> 17/21 and 37/21

My point exactly: Adrien Marie Legendre tried to prove a negative.

> Now, you will agree with me that Legendre was all but a dumb. And he
> even had a proof.

As was shown with your example, this was not a logically valid proof.

> If you want another example: when Whiles published
> his first demonstration of the last theorem of Fermat he was sure the
> proof was right, but an error was found by the reviewers. Then he made
> some changes and no error has been found so far. Now, the point of
> this rigmarole is not that we must proof any assertion concerning C++
> (we are programmers not mathematician) but that we must be careful and
> modest; everybody makes error and the fact that experts are less
> likely to make errors is just an illusion:

They may be less likely to make "obvious" mistakes. This goes for any field.

This is analogous to the advantages of a four-wheel drive car: It lets you
get stuck in inaccessible places. :) You may drive where normal cars can't
go, but if you get stuck, you may need a helicopter to get out. :)

You make this point in the following, as well.

> the "complexity limit" of
> what you get right is just shifted a little further on: you are more
> "exercised" but there's a limit (higher than the limit of a beginner)
> after you are, to say, in foggy land too. In the case of Whiles, the
> demonstration is so complex that not even an expert can state, with a
> reasonable certainty, that it is correct. As to C++, a number of
> experts certainly thought, with reasonable certainty, that the
> specification was correct but then we have a list of hundreds of
> defects. And some of those defects are on *fundamental* aspects of the
> language. Also some of them, e.g. issue 200, are simply incredible for
> their "simplicity". The fact that after 2 years it hasn't been solved
> yet means that it is *too* complex, even for the committee experts.
> There's no offense intended in my words. I think everybody should be
> fair enough to admit that. Sometimes the committee likes to venture
> out to sea, probably because they are fun of the language just like me
> and you (more on this later)

Genny, have I ever said that Rani's proposal has been _proven_ to work? I
have not. I _explicitly_ said that it could be hard to do that, but it might
be possible. What I said is that it works, i.e. we haven't found a case
where it doesn't work. I have _not_ stated that this has been _proven_ to
work.

I know about mathematical and logical formalisms, as well, and I know there
may be a long way from empirical evidence, to actual proof. This doesn't
mean that, as you say yourself here, that if something turns out to work,
even if it may not have been proven, it isn't useful. All I've said is that
it has worked for the examples we have tested it for.

> >>> Not that I'm set for it, but please think about this: can
> >> you give off-hand a proof that Rani's implementation is equivalent to
> >> the mechanical definition I gave above?
> >
> >A proof? Egads. :) I had a hard enough time figuring out how it works, in
> >the first place. :)
>
> So would you trust that code? Would you write it for a client?

We don't have much experience with that component. With more experience, we
may gain higher confidence in it. This goes for C++ itself, as well, its
library, other libraries, etc.

Let me ask you something: Do you have formal proof of the C++ language, or
nontrivial programs of your own? If no, then do you trust those programs?
You may well do that, if you have good experience with them.

Let me put my answer this way: Rani's component does a better job of detecti
ng inheritance than the current techniques, because it also handles multiple
base classes and private inheritance, unlike current techniques. Therefore,
if you want something to reliably detect inheritance, then it seems to be
the best we have, now. This goes back to the point about "obvious" mistakes,
above: It doesn't do the "obvious" mistakes that the current techniques
does, and it seems to handle the other cases. This was also confirmed in a
recent posting by John Maddock.

What's your point? You're talking about now. Do you know any better, perhaps
more proved way, to do it now? If not, then what are you arguing about? I've
already said that if it turns out to not work correctly, we may reconsider
it. However, here and now, it at least doesn't do the obvious mistakes.

> Note
> that this is not an accuse to the code. I like it, and I agree that
> Rani has been very clever to find it out, that's not the point. Also,
> my remark is somewhat more general than specifically addressed to that
> code.
>
> [...]
> >There are a few observations:
> >
> >- is_base_and_derived (Rani's proposal) is usable here and now, so
> >regardless of any language/library change, it may be used now.
>
> Indeed. But I'm seeing that then much of the things we use here are
> being proposed for standardization.

What standardisation? If type traits ends up in the library TR, but some of
it turns out to need compiler support (that is the case already), then that
can be accomodated for.

> That's a different matter. When
> you put them in the language, you will have them forever; so better
> being sure they work. Otherwise I prefer just having them into boost:
> after all that's "standard enough", don't you agree?

There doesn't have to be an either-or. If is_base_and_derived ends up in the
library, it may still be implemented in different ways, including compiler
support, such as a keyword. By having it as a library component, and
implementing it with a keyword with a reserved prefix (as you show below),
you also avoid any name collision with existing conformant code.

> >- If it turns out that is_base_and_derived doesn't completely detect base
> >and derived class, according to the definition in the standard, and a way
is
> >not found to do so within the current definition of the language, one may
> >e.g.:
> > - Change the part of the standard that the is_base_and_derived relies
on
> >for its workings, so that it _does_ work correctly, if possible. Or,
> > - Add is_base_and_derived as an operator in C++0x
>
> The first thing that I've thought when seeing is_base_and_derived<>
> was: how would I implement it if I were a compiler writer? The answer
> (in my mind) was:
>
> template <class B, class D>
> struct is_base_and_derived {
>
> static const bool value = __built_in_is_base_and_derived<B,
> D>::value;
>
> };
>
> Simple and easy. No need to rely on strange overloading and conversion
> ranking rules that, then, could be changed in response to some DR to
> close some other loophole. Probably I would opt for that even if the
> standard provided a normal C++ implementation (except verifying that
> my compiler is able to compile it, especially if it is an
> implementation like Rani's one :-) ).
>
> > On the other hand, if you're able to implement it using the language
> >features, then it may e.g. be a standard library component, and that
won't
> >break any existing programs.
>
> If! Now, to finish exposing my point of view: we are all, I think, C++
> fans, right? Well, we are all *amused* by code like Rani's. We all
> like it, and we are all astonished that something new can be
> discovered in C++ every day, and proud of understanding how it works.

I don't think of it this way. I think it's amazing what kind of reflection
capability C++ has, even without language support. However, as you said,
with language support, such code may be very easy to write. This is nothing
new! This is the story of C and C++. C++ was made to be able to do things
easier and better than you could in C. However, there may still be things
that are hard to do in C++. Which is also why new language features are
under consideration.

As I've said, I've never argued for or against adding this as a core
language feature, at the next revision of the standard. What I have said, is
that it's good that we have the possibility to do it within the language,
already now.

> Ok, now we have it and it is into boost, ready to prove "on the field"
> that it works. So let's use it. When it comes to create new libraries
> or new language features for the standard, then we should all try hard
> to put our passion on one side and think: what we have at hand? Does
> it "seem" to work, or does it work? Isn't it that we want to
> standardize it just for a sort of "pride" to make that clever thing
> available to the world?

By having it in the standard library, it will be available to the world,
yes. Isn't that a good thing? Many may not know about Boost.

I haven't seen an argument against standardising is_base_and_derived,
because its _implementation_ may be done in any way, including using a
keyword. However, if you add a keyword without a reserved prefix, it may
break existing code. Why not standardise a library component, instead, to
avoid such name collision? After all, is_base_and_derived is just one of a
zillion traits. Do you want to add the other traits as keywords (without
reserved prefix), as well. If so, why? Do you find possily breaking a lot of
code better than providing the same facility in the library?

> Why do we want to put it in the standard if we
> have it already in a public available library? Also, as to
> standardizing, the argument you gave
>
> "having it as an operator requires a language change, and that's
> likely several years away"
>
> is moot, because it years away even as library stuff.

What do you mean here? The library TR will be done before a possible next
revision of the standard, and although the TR is not normative, it is likely
that it will also be included in the next version of the standard, and that
library vendors will likely bring their libraries up to conformance with the
TR, when it comes. The point with the TR is to be able to add to the
standard library, without having to wait for the next revision of the
language. Boost's type_traits is one of the libraries under consideration
for the TR.

Regards,

Terje


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