Title
Explicit specialization and friendship
Status
cd2
Section
13.7.5 [temp.friend]
Submitter
Daveed Vandevoorde

Created on 2007-07-06.00:00:00 last changed 143 months ago

Messages

Date: 2010-03-15.00:00:00

[Voted into WP at March, 2010 meeting.]

Date: 2009-10-15.00:00:00

Proposed resolution (October, 2009):

Change 13.7.5 [temp.friend] paragraph 5 as follows:

A member of a class template may be declared to be a friend of a non-template class. In this case, the corresponding member of every specialization of the class template is a friend of the class granting friendship. For explicit specializations the corresponding member is the member (if any) that has the same name, kind (type, function, class template or function template), template parameters, and signature as the member of the class template instantiation that would otherwise have been generated. [Example:

  template<class T> struct A {
    struct B { };
    void f();
    struct D {
      void g();
    };
  };
  template<> struct A<int> {
    struct B { };
    int f();
    struct D {
      void g();
    };
  };

  class C {
    template<class T> friend struct A<T>::B;    // grants friendship to A<int>::B even though
                                                // it is not a specialization of A<T>::B
    template<class T> friend void A<T>::f();    // does not grant friendship to A<int>::f()
                                                // because its return type does not match
    template<class T> friend void A<T>::D::g(); // does not grant friendship to A<int>::D::g()
                                                // because A<int>::D is not a specialization of A<T>::D
  };
Date: 2009-07-15.00:00:00

Notes from the July, 2009 meeting:

The consensus of the CWG was to allow the correspondence of similar members in explicit specializations.

Date: 2007-07-06.00:00:00

Is this code well-formed?

    template <typename T> struct A {
        struct B;
    };

    class C {
        template <typename T> friend struct A<T>::B;
        static int bar;
    };

    template <> struct A<char> {
        struct B {
            int f() {
                return C::bar;   // Is A<char>::B a friend of C?
            }
        };
    };

According to 13.7.5 [temp.friend] paragraph 5,

A member of a class template may be declared to be a friend of a non-template class. In this case, the corresponding member of every specialization of the class template is a friend of the class granting friendship.

This would tend to indicate that the example is well-formed. However, technically A<char>::B does not “correspond to” the same-named member of the class template: 13.9.4 [temp.expl.spec] paragraph 4 says,

The definition of an explicitly specialized class is unrelated to the definition of a generated specialization. That is, its members need not have the same names, types, etc. as the members of a generated specialization.

In other words, there are no “corresponding members” in an explicit specialization.

Is this the outcome we want for examples like the preceding? There is diversity among implementations on this question, with some accepting the example and others rejecting it as an access violation.

History
Date User Action Args
2010-03-29 00:00:00adminsetmessages: + msg2735
2010-03-29 00:00:00adminsetstatus: ready -> cd2
2009-11-08 00:00:00adminsetmessages: + msg2375
2009-11-08 00:00:00adminsetstatus: drafting -> ready
2009-08-03 00:00:00adminsetmessages: + msg2202
2009-08-03 00:00:00adminsetstatus: open -> drafting
2007-07-06 00:00:00admincreate