Balog Pal said:
"Francesco S. Carta"
"In such lattices, explicit qualification can be used to specify which
subobject is meant."
Where "such lattices" refers to this example, given in 10.1 [class.mi]
3:
-------
class L { public: int next; /* ... */ };
class A : public L { /* ... */ };
class B : public L { /* ... */ };
class C : public A, public B { void f(); /* ... */ };
-------
Right after the above sentence, the Standard continues with:
"The body of function C::f could refer to the member next of each L
subobject:
void C::f() { A::next = B::next; }
Without the A:: or B:: qualifiers, the definition of C::f above would
be ill-formed because of ambiguity (class.member.lookup)."
As you can see from the above wording, the qualification is not only
about names, but also, in such cases, about disambiguating subobjects.
Yes it is. Here A and B on the left of ::, being *distinct* types can do the
job.
In your examples you use the *same* type, that is not good to tell a
difference.
Putting the Standard apart for a moment, my point was that my
qualification chain was clear and sufficient to disambiguate the call /
to programmers' eyes/. Then, having realized that the compiler didn't
accept it, I wondered about what the Standard mandated for such
qualifications.
It turned out what it turned out: ill-formed. Not that I care that
much - it isn't a problem at all, it can easily worked around - that's
just something that could easily work - I still believe it would be
trivial to implement, but of course, being just a dust-grain above the
"compiler-implementation-ignorant" level, I could be perfectly
wrong ;-)
Ah, Bjarne really messed up the example, he certainly meant
that should work fine.
Actually, at the time that example has been published, the
Standardization Committee didn't publish the Standard yet (if I'm not
completely mistaken, which can be, indeed), hence it is quite
plausible that Bjarne really meant to write that redundant
qualification.
As well, it is quite possible that his personal compiler did (and
eventually still does) accept and correctly use that qualification
chain - that would be something like a non-compliant extension, wrt
the current Standard... whatever, he does know his job far better than
I do ;-)
I've had a look to the 1996 draft here:
http://www.slac.stanford.edu/BFROOT/www/Computing/Environment/Standards/C++/cd2
[consider that TC++PL 3rd ed. dates back to 1997]
11.2/5 does not appear in that draft - and that's the clause that
finally defines my example as ill-formed.
About this very issue, (1996)11.2/4 covers it insufficiently - look at
the last point of that list, it reads: "-- there exists a base class B
of N that is accessible [...]". Notice how it reads "a base" and not
something more specific along the lines of "one single base" or "one
unambiguous base".
The subsequent example states, in a comment: "Okay: B* can be
implicitly cast to A*", but that's a comment in an example, that's not
within the normative text.
I believe that all of this stuff wasn't really well defined at that
time, otherwise they wouldn't have added 11.2/5 - which puts a final
word on it.
My supposition, once more, is that Bjarne stood on a position very
similar to mine, that is, that the qualification chain could be used
to unequivocally resolve a duplicated base class - a very airborne
supposition of mine, explicitly marked as such ;-)
According to (my understanding of) the Standard, in both of these
expressions...
-------
p->Task::Link::next = 0;
p->Displayed::Link::next = 0;
-------
...the "naming class" is "Link" (that is, the nested class in the
qualification chain), and since a Satellite cannot be implicitly
converted into a Link, those expressions are ill-formed (according to
11.2 [class.access.base] 5).
Actually, the above example doesn't compile in Comeau Online.
Notice how Stroustrup uses a redundant qualification, while the
Standard doesn't - it disambiguates the call without putting L (the
equivalent of Link) in the qualification chain.
Yes, and that extra qual does nothing good to the example.
You're perfectly right - but what about my example? Putting apart the
current Standard for a moment, wouldn't have you looked at my
qualification chain as a perfectly sufficient way to disambiguate that
duplicated base class?
(I'm repeating myself, I know, but here I wanted to make it a direct
question).
As I said in comp.std.c++: "It would be nice if implementations could
allow redundant qualifications in such cases, and it would be even
nicer if a multiple ambiguity such as the one of my example could be
resolved only by climbing the qualification chain, but that would mean
changing the wording in 11.2/4 [errata corrige: I meant to write
"11.2/5"], and I'm not going to propose it."
IMO it would be even nicer BY FAR if we just could use :: directly with
*instances* not just types. The compiler knows the type anyway. (with the
next standard it can be hacked together via decltype, still not noce as the
normal way.) Then it could be used to naturally solve problems like in your
example, and importantly, many real ones too.
Along the same lines: every time the compiler can unambiguously
resolve things for us, the burden should be carried by the compiler,
not by the programmer.
I see little value in changing the existing way for a little artificial
gain, making it easier to work with hierarchies built on guidelines from the
'no-no list'.
As I said, proposing such a change was completely out of my purposes.
Once I realized what the Standard really mandated, I put a full stop
on it - we're discussing this further because you called me on that,
and the discussion is interesting indeed (I discovered some new
things, meanwhile), decisively more light for me, I'm happy you posted
that reply.
And finally: yes, the hierarchy I exemplified is weird. I fully agree.
Maybe some example where it could be reasonable could exist, but this
is a completely different pair of trousers, my point here was only
about the availability of such a feature.
Perhaps they have decided on this direction also to discourage such
hierarchy designs?
That would be perfectly possible and reasonable.