Boost logo

Boost :

From: Gabriel Dos Reis (gdr_at_[hidden])
Date: 2004-02-17 12:56:36


David Vandevoorde <daveed_at_[hidden]> writes:

| (I'm not on the Boost list. Gabriel: Apologies if you
| get this twice. I don't know if you're on the list.
| So to be sure, I left you on the recipients' list.)

{ Don't worry: duplicate messages are automatically deleted. :-)
  I used to read Boost mailing list in batch mode these times, but Dave
  sent about this issue on Boost list with a copy to me and Steve; but
  later, he decided that the issue should be OT. I'm having trouble
  following that part. }

| On Feb 17, 2004, at 6:29 AM, Gabriel Dos Reis wrote:
| [...]
| > Someone has characterized it as inconsistent without giving details as
| > to why; all I'm saying is that, if one accepts the principle that
| > "scopes nest", then the rule is a logical consequence, hence
| > consistent with that principle.
|
| You're making one more assumption: That template
| parameters really have their own full-fledged scope.

No.

I'm reasoning with the -fact- that the scope of template-parameters
encloses the template. That is not an assumption.

| I say that they shouldn't, just as function parameters
| don't.

But, the situation is not similar: template-parameters are introduced
*before* the thingy being parameterized. You'd have the same
situation with function parameters if they were introduced before the
function they are part of (Note: declaring them before the function may
"solve" some of the problems with auto/decltype type-deduction issues
in the auto/decltype proposal).

| > Now, it might be that that logical
| > consequence is unacceptable for some non-rational reasons, but that
| > does not mean the consequence itself is inconsistent.
|
| The current situation is IMO unacceptable for
| _rational_ reasons, no matter what the language-
| legalistic arguments for it may be.

I'm not offering language-legalistic arguments.

In the first message Dave sent to me (which generated this thread), he
said he was just registering a strong opinion. That is not rational
reasons, it is just a statement of feeelings. In subsequent messages,
he made more assertions mostly based on misuderstanding of what I was
proposing.

As I said in another message, if one starts from a principle and you
reach a logical conclusion that is unacceptable to ones believes, the
thing to change is not the conclusion, but the principle that
logically leads to that conclusion. At least, if one wants to stay
consistent.

| > | The POV is that
| > |
| > | class B { typename X };
| > |
| > | template< typename X > class Y // 1
| > | : public B // 2
| > | { // 3
| > | ...
| > | };
| > |
| > | You think that template parameter X is declared in line 1, then
| > hidden
| > | by the base classes name introduced by line 2, thus non-accessible in
| > | line 3, right? You think of the name scopes to nest in the same
| > order,
| > | do you?
| >
| > What I think is: If we accept the principle that scopes should nest,
| > then we should accept its logical consequences; if don't want to
| > accept those logical consequences, then we should abandon the idea
| > that scopes nest. Which one do you want to pick?
|
| As mentioned above, I disagree that these are the
| only options.

Which "only options"? If you make template-parameters hide members,
*then*, you no longer have nesting of scope of the template in the
scope of template-parameters. It is not an option :-)

| But even if you insist on thinking
| in those terms, then there it is still possible
| to come up with a mechanism that matches what most
| of us expect: Simply consider the base class scope
| to enclose the scope of the derived class parameters.

Could you elaborate more on this mechanism? Not that it would not
"solve" this particular issue, but so that I can see whether it
actually works with rest of the rules.

| > | This is a reasonable point of view, actually it's the current
| > | language's interpretation of the topic, but it's not what I call
| > | intuitive.
| >
| > One major problem is what is defined "intuitive" and when "intuitive"
| > is defeated by logic.
|
| Oh please. I notice you posted to the thread "Opinion
| sought on name hiding issue" in comp.lang.c++.moderated.
| Except for you, the other dozen participants seem to
| have no problem on agreeing what is intuitive.
|
| See above for what I think is the flaw in your logic.

You did not point out a flaw. You thought I was assuming something;
which I did not.

| > | While it's technically correct, it still feels wrong - at
| > | least to me.
| >
| > If you think it is wrong, while being consistent with first principle,
| > then propose a a new first principle. The worst thing to do, I
| > believe, is to introduce barnacled hacks that comes from nowhere.
| >
| > | I see things more from a visibility-point-of-view. I
| >
| > "scopes nest" is visitbility-point-of-view :-)
| >
| > | can't see the base class' names at 2,
| >
| > yet, you see the following
| >
| > struct A {
| > struct iterator { };
| > };
| >
| > struct B : A {
| > vodi f(iteraror);
| > };
| >
| > don't you? Or are you proposing that to be ill-formed?
|
| I also see:
|
| struct A { typedef int I; };
| struct B: A {
| typedef long I;
| };
| struct C: B {
| I x; // B::I hides A::I
| };

Exact. So, at least you agree that the issue has nothing particular to
do with templates. As I told you last week, if it is considered
important, it should be solved as a general issue, not added as yet
another special case to the already overly long list of special cases.

| Same with template parameters: They hide the homonyms
| in farther scopes.
|
| > We need general rules on which to decide, we don't need barnacled
| > hacks that would appear "intuitive" at a moment when we don't have a
| > working definition of "intuitive".
| >
| > | I have to go back (that is, I
| > | have to go one "scope" up) to see the names that are contained. This
| > | makes me think of the lines 1 and 2 to be swapped wrt the names they
| > | introduce into the scope of 3. To put it another way: The names of B
| > | are not declared at 2, and that line 2 is also not like a using
| > | declaration, although it might seem similar.
| > |
| > | If we use Dave's or my POV (and we are not alone ;), the
| > advantages of
| > | scopes can be used in this example, too. The advantage is a smaller
| > | scope to search for a name: If you need to know what a name refers
| > to,
| > | you just look into the scopes from the inside (nearest scope), to the
| > | outside. And it feels more natural to me if the scope of the template
| > | parameters is closer than the scope of the class' base(s).
| >
| > If the scope of the template-parameters should come after the scope
| > of base classes -- that is the way I understand you "is closer" --
| > then one would not be able to use template-parameters in base classes.
|
| And you cannot: You can only use them to _name_ base
| classes.

Yes, "name" is what I intended. Sorry. Just to be clear: If
template-parameters had a scope that comes after the scope etablished
by base classes, you could not use them in the naming base classes.

| In fact, now that I reflect on it, base
| classes are not really "enclosing scopes" of derived
| classes. You can simulate the lookup that way, but
| you could just as well say that inheritance is a sort
| of "base class using-directive" (which is how many
| compilers implement it).
|
| > If you don't agree with the "scopes nest" principle, then propose
| > another principle, but please don't label it "intuitive" :-)
|
| On the contrary: If that what Daniel's intuition says,
| he should label it as intuitive.

The point is there: according to *his* intuition.
Do you see what I mean? What we need is a working definition I can
consistently apply to accept of reject conclusions.

| > If I were to design a new programming language, I'm not sure I would
| > just stick to "scopes nest", but here we're not designing a new
| > programming language. IMO, one of the the worst things we can to the
| > already complex C++ scope rules, is to come up with yet another
| > special scope. At this point of complexity, following logical
| > consequences is less evil than "intuitive" hacks where we don't have
| > working definition of "intuitive".
|
| You seem to imply that scope nesting is the only
| mechanism that directs C++ name lookup. That is

I'm actually implying that scope nesting is the first principle that
directs C++ name lookup rule, and things like ADL are local deviations
that reserve occasional confusions (I already mentioned that, but
since you don't read Boost mailing lists you probably have missed the
mention to that deviation). And those deviations are causing many
confusions for many people.
Two weeks ago, I had a serious discussion on that topic with Bjarne
[ any discussions that followed on the CWG reflector were purely
  coincidental, but the fact he brought up an example he thought
  should be covered by nesting effect is, I guess, a sign that he
  thinks, scope nesting guides C++ name lookup rules. That guidance is
  not full, as examplified by local barnacled rules, but for the most
  majority part, it is the guiding principle. ]

| not the case though (using directives, using
| declarations, and ADL don't work that way; inheritance
| doesn't really work that way either).

Whowever they have been worded to display the effect of nesting scopes
(except access-checking for using-declaration at class-scope).

| Anyway, as many have pointed out, enabling sound
| C++ engineering requires the current situation to
| be fixed.

As you know (since we have been discussing this issue for some time
now), I don't disagree with the idea that something should be done. I
disagree on the -specific- suggestion of parallel scope or enclosing
scopes being injected into enclosed scopes.
Did I disagree that anything should be done, I would not have made the
proposal in the first place.

-- Gaby


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