Topic: Defect Report: Friend syntax ambiguous


Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1999/06/16
Raw View
scott douglass <sdouglass@arm.com> writes:

>     A :: B :: C () { }
>
> Is this the definition of ::C() which returns ::A::B or of ::B::C() which
> returns ::A?

Interesting. I thought this was ill-formed, but I couldn't find the
words. 7.3.1.2, [namespace.memdef]/2 says

>> Members of a named namespace can also be defined outside that
>> namespace by explicit qualification (3.4.3.2) of the name being
>> defined,

Then, 3.4.2/6 says

>> In a declaration for a namespace member in which the declarator=ADid
>> is a qualified=ADid, given that the qualified=ADid for the namespace
>> member has the form
>>   nested=ADname=ADspecifier unqualified=ADid
>> the unqualified=ADid shall name a member of the namespace designated
>> by the nested=ADname=ADspecifier.

In this context, qualified-id may be

   ::(opt) nested=ADname=ADspecifier template(opt) unqualified=ADid

but the wording clearly excludes the optional :: and the optional
template. So, while this phrase makes

namespace A{}
void A::foo(){}

ill-formed (no prior declaration of A::foo), the construct

namespace B{}
void ::B::foo(){}

would not be ill-formed according to that clause (depending on what
"given that" means in the English language). However, if that
paragraph is meant to make ::B::foo ill-formed, anyway, then your
example is clearly ill-formed: A::B::C() couldn't possibly a
declaration for a namespace member...

As they say: My brain hurts.

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: scott douglass <sdouglass@arm.com>
Date: 1999/06/11
Raw View
Martin von Loewis wrote:
>
> The example below is ambiguous.
>
> struct A{
>   struct B{};
> };
>
> A::B C();
>
> namespace B{
>   A C();
> }
>
> struct Test{
>   friend A::B ::C();
> };

I agree that this is ambiguous, but the ambiguity can arise in any delcaration
not just friend declarations.  Consider:

    A :: B :: C () { }

Is this the definition of ::C() which returns ::A::B or of ::B::C() which
returns ::A?  Or even an (illegal) attempt to define ::A::B::C() with no
specified return type.


[ 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: loewis@informatik.hu-berlin.de (Martin von Loewis)
Date: 1999/06/07
Raw View
[ Moderator's note: Forwarded to C++ Committee -sdc ]

The example below is ambiguous.

struct A{
  struct B{};
};

A::B C();

namespace B{
  A C();
}


struct Test{
  friend A::B ::C();
};

Here, it is not clear whether the friend declaration denotes
A B::C(), or A::B C(), yet the standard does not resolve this
ambiguity.

The ambiguity arises since both the simple-type-specifier (7.1.5.2,
[dcl.type.simple]/1) and an init-declararator (8, [dcl.decl]/1)
contain an optional :: and an optional nested-name-specifier (5.1,
[expr.prim]/1). Therefore, two different ways to analyse this code are
possible:

simple-type-specifier = A::B
init-declarator = ::C()
simple-declaration = friend A::B ::C();

or

simple-type-specifier = A
init-declarator = ::B::C()
simple-declaration = friend A ::B::C();

(For simple-declaration, see 7, [dcl.dcl]/1)

Since it is a friend declaration, the init-declarator may be
qualified, and start with a global scope.

Proposed Resolution: In the definition of nested-name-specifier, add a
sentence saying that a :: token immediately following a
nested-name-specifier is always considered as part of the
nested-name-specifier. Under this interpretation, the example is
ill-formed, and should be corrected as either

friend A (::B::C)(); //or
friend A::B (::C)();

Please let me know if you need further information.

Regards,
Martin v. L   wis


[ 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              ]