This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


47. Template friend issues

Section: 13.7.5  [temp.friend]     Status: NAD     Submitter: John H. Spicer     Date: 7 Nov 1997

Issue 1

Paragraph 1 says that a friend of a class template can be a template. Paragraph 2 says: A friend template may be declared within a non-template class. A friend function template may be defined within a non-template class.

I'm not sure what this wording implies about friend template definitions within template classes. The rules for class templates and normal classes should be the same: a function template can be declared or defined, but a class template can only be declared in a friend declaration.

Issue 2

Paragraph 4 says: When a function is defined in a friend function declaration in a class template, the function is defined when the class template is first instantiated. I take it that this was intended to mean that a function that is defined in a class template is not defined until the first instantiation. I think this should say that a function that is defined in a class template is defined each time the class is instantiated. This means that a function that is defined in a class template must depend on all of the template parameters of the class template, otherwise multiple definition errors could occur during instantiations. If we don't have a rule like this, compilers would have to compare the definitions of functions to see whether they are the same or not. For example:

    template <class T> struct A {
            friend int f() { return sizeof(T); }
    };

    A<int> ai;
    A<long> ac;
I hope we would all agree that this program is ill-formed, even if long and int have the same size.

From Bill Gibbons:

[1] That sounds right.

[2] Whenever possible, I try to treat instantiated class templates as if they were ordinary classes with funny names. If you write:

    struct A_int {
        friend int f() { return sizeof(int); }
    };
    struct A_long {
        friend int f() { return sizeof(long); }
    };
it is a redefinition (which is not allowed) and an ODR violation. And if you write:
    template <class T, class U> struct A {
                friend int f() { return sizeof(U); }
    };

    A<int,float> ai;
    A<long,float> ac;
the corresponding non-template code would be:
    struct A_int_float {
        friend int f() { return sizeof(float); }
    };
    struct A_long_float {
        friend int f() { return sizeof(float); }
    };
then the two definitions of "f" are identical so there is no ODR violation, but it is still a redefinition. I think this is just an editorial clarification.

Rationale (04/99): The first sub-issue reflects wording that was changed to address the concern before the IS was issued. A close and careful reading of the Standard already leads to the conclusion that the example in the second sub-issue is ill-formed, so no change is needed.