Title
Name lookup in friend declarations
Status
cd2
Section
6.5.3 [basic.lookup.unqual]
Submitter
Ben Hutchings

Created on 2004-12-07.00:00:00 last changed 179 months ago

Messages

Date: 2010-03-15.00:00:00

[Voted into WP at March, 2010 meeting.]

Date: 2010-02-15.00:00:00

Proposed resolution (February, 2010):

Change 6.5.3 [basic.lookup.unqual] paragraph 10 as follows:

In a friend declaration naming a member function, a name used in the function declarator and not part of a template-argument in a template-id the declarator-id is first looked up in the scope of the member function's class (6.5.2 [class.member.lookup]). If it is not found, or if the name is part of a template-argument in a template-id the declarator-id, the look up is as described for unqualified names in the definition of the class granting friendship. [Example:

    struct A {
      typedef int AT;
      void f1(AT);
      void f2(float);
      template<typename T> void f3();
    };
    struct B {
      typedef char AT;
      typedef float BT;
      friend void A::f1(AT);    // parameter type is A::AT
      friend void A::f2(BT);    // parameter type is B::BT
      friend void A::f3<AT>();  // template argument is B::AT
    };

end example]

Date: 2005-04-15.00:00:00

Notes from the April, 2005 meeting:

The phrase “looked up in the scope of [a] class” occurs frequently throughout the Standard and always refers to the member name lookup described in 6.5.2 [class.member.lookup]. This is the first interpretation mentioned above (“only members of the class and its base classes”), resolving s1 to ns::s1. A cross-reference to 6.5.2 [class.member.lookup] will be added to 6.5.3 [basic.lookup.unqual] paragraph 10 to make this clearer.

In discussing this question, the CWG noticed another problem: the text quoted above applies to all template-arguments appearing in the function declarator. The intention of this rule, however, is that only template-arguments in the declarator-id should ignore the member function's class scope; template-arguments used elsewhere in the function declarator should be treated like other names. For example:

     template<typename T> struct S;
     struct A {
       typedef int T;
       void foo(S<T>);
     };
     template <typename T> struct B {
       friend void A::foo(S<T>);  // i.e., S<A::T>
     };
Date: 2004-12-07.00:00:00

When 6.5.3 [basic.lookup.unqual] paragraph 10 says,

In a friend declaration naming a member function, a name used in the function declarator and not part of a template-argument in a template-id is first looked up in the scope of the member function's class. If it is not found, or if the name is part of a template-argument in a template-id, the look up is as described for unqualified names in the definition of the class granting friendship.

what does “in the scope of the member function's class” mean? Does it mean that only members of the class and its base classes are considered? Or does it mean that the same lookup is to be performed as if the name appeared in the member function's class? Implementations vary in this regard. For example:

     struct s1;

     namespace ns {
         struct s1;
     }

     struct s2 {
         void f(s1 &);
     };

     namespace ns {
         struct s3 {
             friend void s2::f(s1 &);
         };
     }

Microsoft Visual C++ and Comeau C++ resolve s1 in the friend declaration to ns::s1 and issue an error, while g++ resolves it to ::s1 and accepts the code.

History
Date User Action Args
2010-03-29 00:00:00adminsetmessages: + msg2659
2010-03-29 00:00:00adminsetstatus: tentatively ready -> cd2
2010-02-16 00:00:00adminsetmessages: + msg2490
2010-02-16 00:00:00adminsetstatus: drafting -> tentatively ready
2005-05-01 00:00:00adminsetmessages: + msg1155
2005-05-01 00:00:00adminsetstatus: open -> drafting
2004-12-07 00:00:00admincreate