Boost logo

Boost :

From: Gabriel Dos Reis (gdr_at_[hidden])
Date: 2004-02-17 06:29:25


Daniel Frey <daniel.frey_at_[hidden]> writes:

| Gabriel Dos Reis wrote:
| > David Abrahams <dave_at_[hidden]> writes:
| > | > What is bizarre and inconsistent about it and is not with the
| > other
| > | > alternatives you care to name? | | As I expected my example
| > below to demonstrate, I think it's
| > | inconsistent with the way names from non-dependent base classes are
| > | dealt with when masked by function parameter names.
| > But function parameters are not template parameters vice versa. And
| > you should not expect them to behave the same without providing
| > technical reasons why such expectations may take place.
| > The fundamental difference between them is the places where they are
| > declared. The scope of template-parameters *encloses* the template --
| > that is why members of non-dependent bases hide them -- whereas member
| > functions *are enclosed* by the scope (non-dependent) base classes
| > -- which is why those function parameters can hide members in base
| > classes. An action that would be consistent is to leave the current
| > rule as is
| > -- but some people been saying that that consistent behaviour goes
| > against their intuition.
|
| Apologies in advance if I jump in too quickly without fully
| understanding your point, but to me it seems that the current rule is
| consistent only when viewed from a certain point of view.

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

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

| 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?

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.

If you don't agree with the "scopes nest" principle, then propose
another principle, but please don't label it "intuitive" :-)

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

-- Gaby


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