Topic: Defect Report: Membership of using-directive names


Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: 2000/05/31
Raw View
Martin von Loewis <loewis@informatik.hu-berlin.de> wrote:

> joerg.barfurth@attglobal.net (Joerg Barfurth) writes:
>=20
> > No. In (7.3.4/1) it says (all Standard quotes according to the OP. I
> > didn't manage to look them up myself yet):=3D20
> > "A using-directive specifies that the names in the nominated namespac=
e
> > can be used in the scope in which the using-directive appears ..."
> >=20
> > This can be translated as 'The *names* in the nominated namespace,
> > become *visible* in the scope in which the using-directive appears.'.
>=20
> No, such a translation would be incorrect. The first sentence gives a
> rationale for having a using-directive in the language. It does not
> (fully) define its meaning. The actual meaning is given in the next
> sentence, which says that the names appear in the nearest enclosing
> scope. Typically, that means that the names can be used unqualified,
> but there are counter-examples.

Well, usually when a name becomes visible in a scope, its declarative
region contains the remainder of that scope (unless it is hidden in
nested scopes).

Note: IMHO the first sentence says that the *names* becomes *visible*.
The next sentence doesn't talk about visibility, nor about names. It
talks about declarations.=20
Effectively these declarations also become visible (but only for the
purpose of unqualified name look up) in the inner scope only. They
remain in their original namespace of course, but (during unqualified
lookup) are treated as though they appeared in the outer (enclosing)
scope.

> > So the names become visible only in the scope of the using directive,
> > but their declarations *appear* to be in that enclosing namespace.
>=20
> Indeed. As soon as the scope containing the using-directive is closed,
> the names won't appear in the nearest enclosing scope anymore - the
> using-directive only applies to the scope in which it appears.

IMHO this means that one cannot say that neither the names nor even
these declarations of those names become visible in the nearest
enclosing scope. Apperently the OP reads this as I do.

'Visible' is not about where something is seen, but about the (prior)
question whether it can be seen at all. The (unique) scope where the
names and their declarations become visible (due to the using directive)
is the scope where the using directive appears.

[SNIP my example]

> This example is certainly ill-formed. However, "visibility" does not
> matter here. foo is an unqualified name, so the rules of 3.4.1 apply,
> which in turn refer to the rules in 7.3.4 and 3.4.2. Neither one helps
> finding a definition of foo, so 3.4.1/5 applies. The name foo is not
> defined in Enclosing, and not defined globally, so the program is
> ill-formed.
>=20
> > The name 'foo' is visible in Enclosing::B.
>=20
> Correct.

And it is not visible in Enclosing.

> > The declaration of 'int Enclosing::A::foo()' would appear to be in
> > namespace Enclosing, if 'foo' is used in namespace Enclosing::B.
>=20
> I don't think the term "appear" is very helpful, either: You can't use
> "Enclosing::foo" inside Enclosing::B; but you could use
> Enclosing::B::foo, since rules for qualified lookup are yet different.

I did talk about using (unqualified) 'foo', so unqualified name lookup
clearly applies. From how it was introduced above, you could infer that
'appear to be in X' here means 'Is treated during (unqualified) name
lookup as if in X'.

> > The declaration would thereby become visible (at most) in the scope o=
f
> > the using directive (in this case namespace Enclosing::B).
>=20
> I interpreted "they become visible in" as "they become visible, and
> they are in". So while they are visible only as long as the
> using-directive is in scope, they can be seen as existing in the
> nearest enclosing namespace ...

Well, certainly *they are not in*. But for a certain purpose they are
treated, as though they were in.=20
I do not see the justification for interpreting=20
     "they become visible in a namespace ..."=20
as=20
     "they become visible in a scope; and for some purpose to be
      mentioned later they are treated as though they were in a
      namespace..."

And the sentence that says "they become visible in" does not even
mention that purpose (i.e. unqualified name lookup).=20
Rather, the next sentence tells about how this affects unqualified name
lookup. As you admitted yourself in your first post, the first sentence
serves to determine the referent of "the namespace" in the second one.=20

If the first sentence already presupposes unqualified name lookup, the
second sentence is misleading, and the whole paragraph (3.4.1/2) becomes
circular. It should be replaced by=20
     "Wrt using directives see 7.3.4/2."

BTW: there is a discrepancy that seemed important to me at first sight:
The first sentence of (7.3.4/1) talks about *names* while the first
sentence of (3.4.1/2) talks about declarations (?).

> > But then the second sentence of (3.4.1/2) contradicts the second
> > sentence in (7.3.4/1).
>=20
> No. Please note that "visible" is not a well-defined term in the C++
> standard. Instead, "scope", "declarative region", "hiding" and "name
> lookup" are used to describe how a use of a name is bound to a
> definition.

But then the use of "visible" in this context is either wrong or
misleading or (at least) ambiguous.

> > I assume that was the intent, but it is not what is in the standard.
>=20
> Sure it is. The crucial thing here is that "being visible" is an
> abstraction from the real procedures that apply. There are many
> aspects to name binding, and these aspects are described in detailed
> procedures, starting with name lookup, then template argument
> deduction, overload resolution, and access check.=20
>=20
> To describe these procedures, one has to give both overview
> statements, and detailed description. 3.4.1/2 clearly is an overview
> statement, as it explicitly refers to the detailed procedure in 7.3.4.

If it is misleading or wrong, it still should be corrected. The
correction would be a minor one and not change the (intended and
implemented) semantics.

Proposed Resolution:

Change 3.4.1 [basic.lookup.unqual] paragraph 2 to:
"The declarations from the namespace nominated by a using-directive
become visible in the scope of using-directive. For the purpose of the
unqualified name look up rules described in this 3.4.1, the declarations
from the namespace nominated by the using-directive are considered
members of a namespace enclosing the using-directive; see 7.3.4"

> Regards,
> Martin

J=F6rg

--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
--------------- =7F=7F=7Fusing std::disclaimer; ------------------
Software Engineer                     joerg.barfurth@germany.sun.com
Star Office GmbH                      =7Fhttp://www.sun.com/staroffice

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/05/26
Raw View
Hideaki Onaru <gomarine@mx1.ttcn.ne.jp> writes:

[3.4.1/2]
> "The declarations from the namespace nominated by a using-directive become
> visible in a namespace enclosing the using-directive; see 7.3.4. For the
> purpose of the unqualified name look up rules described in this 3.4.1, the
> declarations from the namespace nominated by the using-directive are
> considered members of that enclosing namespace."

[...]

> On the other hand, according to 3.4.1 [basic.lookup.unqual], i in f() is
> ambiguous between A::i and B::i.

It may be confusing use of the English language, but I don't think
there is an actual defect. The last sentence refers to "that enclosing
namespace", and the "that" apparently refers to the namespace mention
in the first sentence.

Now, that says "in *a* namespace enclosing the using-directive". It
does not say "in the namespace immediately enclosing the
using-directive", so it is vague, and refers to 7.3.4 for details.

In 7.3.4, it explains that the name appears in the nearest enclosing
namespace containing both declarations, which does not contradict the
claim in 3.4.1.

So in your example, i is clearly B::i, the access is not ambiguous.

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: 2000/05/26
Raw View
Martin von Loewis <loewis@informatik.hu-berlin.de> wrote:

> Hideaki Onaru <gomarine@mx1.ttcn.ne.jp> writes:
>=20
> [3.4.1/2]
> > "The declarations from the namespace nominated by a using-directive b=
ecome
> > visible in a namespace enclosing the using-directive; see 7.3.4. For =
the
> > purpose of the unqualified name look up rules described in this 3.4.1=
, the
> > declarations from the namespace nominated by the using-directive are
> > considered members of that enclosing namespace."
>=20
> [...]
>=20
> > On the other hand, according to 3.4.1 [basic.lookup.unqual], i in f()=
 is
> > ambiguous between A::i and B::i.

> It may be confusing use of the English language, but I don't think
> there is an actual defect. The last sentence refers to "that enclosing
> namespace", and the "that" apparently refers to the namespace mention
> in the first sentence.=20

Agreed.
=20
> Now, that says "in *a* namespace enclosing the using-directive". It
> does not say "in the namespace immediately enclosing the
> using-directive", so it is vague, and refers to 7.3.4 for details.

Agreed. But note that it says "The declarations ... become *visible* in
a namespace ...". =20

> In 7.3.4, it explains that the name appears in the nearest enclosing
> namespace containing both declarations, which does not contradict the
> claim in 3.4.1.
<nit> a using-directive is not really a declaration ...</nit>

No. In (7.3.4/1) it says (all Standard quotes according to the OP. I
didn't manage to look them up myself yet):=20
"A using-directive specifies that the names in the nominated namespace
can be used in the scope in which the using-directive appears ..."

This can be translated as 'The *names* in the nominated namespace,
become *visible* in the scope in which the using-directive appears.'. It
then goes on to explain that=20
"During unqualified name look up (3.4.1), the names appear as if they
were declared in the nearest enclosing namespace ..."

So the names become visible only in the scope of the using directive,
but their declarations *appear* to be in that enclosing namespace.

Obviously, the declarations do not become visible in that enclosing
namespace, or else:

namespace Enclosing {
  namespace A { int foo(); }
  namespace B { using namespace A; }
  int i =3D foo(); // calls A::foo ?
}

I think the declaration of Enclosing::A::foo would not be visible in
namespace Enclosing.=20
The name 'foo' is visible in Enclosing::B.=20
The declaration of 'int Enclosing::A::foo()' would appear to be in
namespace Enclosing, if 'foo' is used in namespace Enclosing::B.

The declaration would thereby become visible (at most) in the scope of
the using directive (in this case namespace Enclosing::B).

That in turn means that in (3.4.1/2) the namespace in which
'declarations ... become visible' can only be the one directly
containing the using-directive. (How about block scope using-directives
? No namespace really qualifies there.)

But then the second sentence of (3.4.1/2) contradicts the second
sentence in (7.3.4/1).
=20
> So in your example, i is clearly B::i, the access is not ambiguous.

I assume that was the intent, but it is not what is in the standard.
Adding in using-declarations at block scope serves to increase the
confusion.=20

Regards
-- J=F6rg

> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with=
 ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu   =
 ]
> [              --- Please see the FAQ before posting. ---              =
 ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html             =
 ]


--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
--------------- =7F=7F=7Fusing std::disclaimer; ------------------
Software Engineer                     joerg.barfurth@germany.sun.com
Star Office GmbH                      =7Fhttp://www.sun.com/staroffice

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/05/27
Raw View
joerg.barfurth@attglobal.net (Joerg Barfurth) writes:

> No. In (7.3.4/1) it says (all Standard quotes according to the OP. I
> didn't manage to look them up myself yet):=20
> "A using-directive specifies that the names in the nominated namespace
> can be used in the scope in which the using-directive appears ..."
>
> This can be translated as 'The *names* in the nominated namespace,
> become *visible* in the scope in which the using-directive appears.'.

No, such a translation would be incorrect. The first sentence gives a
rationale for having a using-directive in the language. It does not
(fully) define its meaning. The actual meaning is given in the next
sentence, which says that the names appear in the nearest enclosing
scope. Typically, that means that the names can be used unqualified,
but there are counter-examples.

> So the names become visible only in the scope of the using directive,
> but their declarations *appear* to be in that enclosing namespace.

Indeed. As soon as the scope containing the using-directive is closed,
the names won't appear in the nearest enclosing scope anymore - the
using-directive only applies to the scope in which it appears.

> Obviously, the declarations do not become visible in that enclosing
> namespace, or else:
>
> namespace Enclosing {
>   namespace A { int foo(); }
>   namespace B { using namespace A; }
>   int i = foo(); // calls A::foo ?
> }
>
> I think the declaration of Enclosing::A::foo would not be visible in
> namespace Enclosing.

This example is certainly ill-formed. However, "visibility" does not
matter here. foo is an unqualified name, so the rules of 3.4.1 apply,
which in turn refer to the rules in 7.3.4 and 3.4.2. Neither one helps
finding a definition of foo, so 3.4.1/5 applies. The name foo is not
defined in Enclosing, and not defined globally, so the program is
ill-formed.

> The name 'foo' is visible in Enclosing::B.

Correct.

> The declaration of 'int Enclosing::A::foo()' would appear to be in
> namespace Enclosing, if 'foo' is used in namespace Enclosing::B.

I don't think the term "appear" is very helpful, either: You can't use
"Enclosing::foo" inside Enclosing::B; but you could use
Enclosing::B::foo, since rules for qualified lookup are yet different.

> The declaration would thereby become visible (at most) in the scope of
> the using directive (in this case namespace Enclosing::B).

I interpreted "they become visible in" as "they become visible, and
they are in". So while they are visible only as long as the
using-directive is in scope, they can be seen as existing in the
nearest enclosing namespace ...

> But then the second sentence of (3.4.1/2) contradicts the second
> sentence in (7.3.4/1).

No. Please note that "visible" is not a well-defined term in the C++
standard. Instead, "scope", "declarative region", "hiding" and "name
lookup" are used to describe how a use of a name is bound to a
definition.

> I assume that was the intent, but it is not what is in the standard.

Sure it is. The crucial thing here is that "being visible" is an
abstraction from the real procedures that apply. There are many
aspects to name binding, and these aspects are described in detailed
procedures, starting with name lookup, then template argument
deduction, overload resolution, and access check.

To describe these procedures, one has to give both overview
statements, and detailed description. 3.4.1/2 clearly is an overview
statement, as it explicitly refers to the detailed procedure in 7.3.4.

Regards,
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]