Title
Grammar does not allow "friend class A<int>;"
Status
tc1
Section
9.2.9.5 [dcl.type.elab]
Submitter
Mike Ball

Created on 1998-10-17.00:00:00 last changed 255 months ago

Messages

Date: 2000-10-15.00:00:00

Proposed resolution (10/00):

Change the grammar in 9.2.9.5 [dcl.type.elab] to read

    elaborated-type-specifier:
      class-key ::opt nested-name-specifieropt identifier
      class-key ::opt nested-name-specifieropt templateopt template-id
      enum ::opt nested-name-specifieropt identifier
      typename ::opt nested-name-specifier identifier
      typename ::opt nested-name-specifier templateopt template-id
and change the forms allowed in paragraph 1 to
    class-key identifier ;
    friend class-key ::opt identifier ;
    friend class-key ::opt template-id ;
    friend class-key ::opt nested-name-specifier identifier ;
    friend class-key ::opt nested-name-specifier templateopt template-id ;

Date: 2003-04-25.00:00:00

I can't find the answer to the following in the standard. Does anybody have a reference?

The syntax for elaborated type specifier is

    elaborated-type-specifier:
      class-key ::opt nested-name-specifieropt identifier
      enum ::opt nested-name-specifieropt identifier
      typename ::opt  nested-name-specifier identifier
      typename ::opt  nested-name-specifier templateopt template-id

    If an elaborated-type-specifier is the sole constituent of a declaration, the declaration is ill-formed unless it is an explicit specialization (13.9.4 [temp.expl.spec] ), an explicit instantiation (13.9.3 [temp.explicit] ) or it has one of the following forms:

      class-key identifier ;
      friend class-key identifier ;
      friend class-key :: identifier ;
      friend class-key nested-name-specifier identifier ;
Which does not allow the production

    class foo<int> // foo is a template
On the other hand, a friend declaration seems to require this production,
An elaborated-type-specifier shall be used in a friend declaration for a class.*

[Footnote: The class-key of the elaborated-type-specifier is required. —end footnote]

And in 13.7.5 [temp.friend] we find the example
[Example:
    template<class T> class task;
    template<class T> task<T>* preempt(task<T>*);

    template<class T> class task {
        // ...
        friend void next_time();
        friend void process(task<T>*);
        friend task<T>* preempt<T>(task<T>*);
        template<class C> friend int func(C);

        friend class task<int>;
        template<class P> friend class frd;
        // ...
    };
Is there some special dispensation somewhere to allow the syntax in this context? Is there something I've missed about elaborated-type-specifier? Is it just another bug in the standard?

An additional problem was reported via comp.std.c++: the grammar does not allow the following example:

    namespace A{
      class B{};
    };

    namespace B{
      class A{};
      class C{
	friend class ::A::B;
      };
    };
History
Date User Action Args
2003-04-25 00:00:00adminsetstatus: dr -> tc1
2000-11-18 00:00:00adminsetstatus: review -> dr
2000-05-21 00:00:00adminsetstatus: drafting -> review
1999-09-14 00:00:00adminsetmessages: + msg97
1999-09-14 00:00:00adminsetstatus: open -> drafting
1998-10-17 00:00:00admincreate