Какое пространство имен содержит объявление этой функции-друга?

friend Функция ниже не найдена обычным поиском (§7.3.1.2/3), но найдена ADL (§3.4.2/4 вторая точка маркера), поэтому код компилируется и выполняется нормально ( пример в реальном времени). Но функция f не объявлено ни в одном пространстве имен. Например, если вы попытаетесь заменить вызов f(x); по любому из этих вызовов ::f(x);, A::f(x); или же A::X::f(x);код не скомпилируется. Какое пространство имен содержит объявление этой функции-друга? Стандарт говорит что-нибудь об этом?

#include <iostream>
namespace A {
    class X {
        int i;
        friend void f(X x) { std::cout << x.i << '\n'; }
    public:
        X():i(101){}
    };
}

int main()
{
    A::X x;
    f(x);
}

1 ответ

Решение

Из стандарта C++

11.3 Друзья

6 Функция может быть определена в объявлении друга класса тогда и только тогда, когда класс является нелокальным классом (9.8), имя функции является неквалифицированным, а функция имеет область пространства имен. [ Пример:

class M { friend void f() { } // definition of global f, a friend of M,
                              // not the definition of a member function
};

- конец примера]

И другую цитату (7.3.1 Определение пространства имен)

3 Каждое имя, впервые объявленное в пространстве имен, является членом этого пространства имен. Если объявление друга в нелокальном классе сначала объявляет класс, функцию, шаблон класса или шаблон функции 98, то друг является членом внутреннего внутреннего пространства имен. Объявление друга само по себе не делает имя видимым для неквалифицированного поиска (3.4.1) или квалифицированного поиска (3.4.3). [Примечание: имя друга будет отображаться в его пространстве имен, если в области имен пространства предоставляется соответствующее объявление (до или после определения класса, предоставляющего дружбу). - конец примечания] Если вызывается функция или шаблон функции друга, ее имя может быть найдено с помощью поиска имен, который рассматривает функции из пространств имен и классов, связанных с типами аргументов функции (3.4.2). Если имя в объявлении друга не является ни квалифицированным, ни идентификатором шаблона, а объявление является функцией или разработанным спецификатором типа, поиск, чтобы определить, был ли объект ранее объявлен, не должен рассматривать какие-либо области за пределами самого внутреннего окружающего пространства имен, [Примечание: другие формы объявлений друзей не могут объявлять нового члена внутреннего вложенного пространства имен и, следовательно, следовать обычным правилам поиска. —Конечная записка]

Я хотел бы отметить, что включение имени функции в скобках подавляет поиск, зависящий от аргумента.

Для этого кода

int main()
{
    A::X x;
    ( f )(x);
}

функция f не будет найдена.

Другие вопросы по тегам