This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118c. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-10-11
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.