«Язык программирования C ++, 3-е издание (Stroustrap)»: p279:
I. «Как и декларация члена, декларация друга не вводит имя в ограничивающую область»
II. «Класс друга должен быть ранее объявлен во вложенной области видимости или определен в неклассе
область действия, сразу включающая класс, объявляющий его другом "
III. «Другую функцию можно явно объявить так же, как дружественные классы, или ее можно найти через типы аргументов (§8.2.6), как если бы она была объявлена в неклассе
область действия, сразу же включающая его класс. "
IV. «Из этого следует, что функция друга должна быть явно объявлена во вложенной области видимости или принимать аргумент своего класса. Если нет, друга нельзя вызвать. Например:«
//no f() here
void g();
class X{
friend void f(); //useless
friend void g(); //can be found because it is declared outside of class scope
friend void h(const X&); //can be found because the arguments access class members
};
void f() { } //enemy of X :)
Но в вашем случае есть еще кое-что, что связано с пространством имен, потому что если вы поместите правильное объявление в foo, например ::1122*
namespace foo{
struct bar{
friend void baz(const &bar){};
void call_friend();
}
}
не компилируется. Тем не менее, если вы объявите это за пределами foo, это работает как шарм. Теперь рассмотрим, что на самом деле глобальные, локальные, структура и классы фактически являются пространствами имен. Теперь это приводит к выводу, что baz(const &)
неявно определен в глобальной области видимости.
Это компилируется:
namespace foo{
struct bar{
friend void baz(const bar&){};
void call_friend();
};
}
int main(){
foo::bar k;
baz(k);
return 0;
}
Следовательно, есть две проблемы:
- Объявление друга не вводит имя во вложенной области видимости, если только IV. Таким образом, исходная программа не может найти baz (), поскольку она не была должным образом объявлена.
- Если IV, то есть ADL, то функция находится в foo, но недоступна как foo :: baz (k) из-за ADL. Вам нужно будет явно указать baz (const bar &) в foo, чтобы получить доступ к нему по определенному имени.
Спасибо, надеюсь, это поможет, но, конечно, мне понравился вызов :).