В поисках соответствующего правила, которое гласит, что friend
определение неквалифицированного имени функции всегда является членом пространства имен, я обнаружил, что это не совсем так. [Namespace.memdef] / 3:
Если объявление friend
в нелокальном классе сначала объявляет класс, функцию, шаблон класса или шаблон функции, то друг является членом внутреннего вложенного пространства имен. ... Если имя в объявлении friend
не является ни квалифицированным, ни template-id , и объявление является функцией или подробный спецификатор типа , поиск для определения независимо от того, была ли ранее объявлена сущность, она не должна рассматривать какие-либо области за пределами самого внутреннего вмещающего пространства имен.
Данное требование относится только к определениям функций и исключает локальный класс друзей или квалифицированное имя друга. Но это оставляет возможность template-id в качестве имени функции.
Таким образом, формулировка, похоже, имеет значение в этом коде:
struct A {
template <typename T>
static void f();
template <typename T>
struct B {
friend void f<T>() {}
};
};
Здесь в объявлении друга указано имя template-id , поэтому правило о пропуске областей, не относящихся к пространству имен, не применяется, и f
действительно называет шаблон функции A::f
. Поэтому [class.friend] / 6 говорит, что это неправильно, хотя, если бы объявление friend
не было определением, оно было бы правильно сформировано.