С чем связано ограничение на объявление friend функций в локальных классах?
class A {
friend void foo(){}; // OK
};
int main() {
class B {
friend void foo(){}; // ERROR
};
}
Объявлять дружественные функции к локальном классе вам никто не запрещает. В вашем примере срабатывает не ограничение на объявление дружественных функций как таковое, а ограничение на определение дружественных функций прямо внутри определения локального класса.
Можно сказать что ситуация проистекает из особенностей использования неквалифицированного имени во friend-объявлениях в локальных классах. Квалифицированные имена во friend-объявлениях использовать можно обычным образом (т.е., как всегда с квалифицированными именами, такие friend-объявления должны ссылаться на уже известные функции)
void foo() {}
int main()
{
class A {
friend void foo(); // <- Так нельзя
};
class B {
friend void ::foo(); // <- А так можно
};
}
Особенность же неквалифицированного имени заключается в том, что по правилам friend-объявлений, такое объявление ссылается на сущность в ближайшей охватывающей не-класс области видимости. В вышеприведенном примере friend-объявление в классе A
ссылается на имя функции foo
, локальное в main
.
Такая трактовка неквалифицированного имени необходима потому, что это - единственный способ, при помощи которого локальные классы могут ссылаться друг на друга. По понятным причинам квалифицированных имен у таких классов нет.
Что интересно, "спасти" такое friend-объявление еще можно, если насильно "притащить" в локальную область видимости объявление существующей функции с таким именем
void foo() {}
int main()
{
void foo(); // Объявление ссылается на `::foo`
class A {
friend void foo(); // <- Так можно
// Ссылается на локальное имя `foo` в main, которое ссылается на `::foo`
};
}
Но к определениям новых функций (как в вашем примере) эта лазейка не относится - оно бы фактически пыталось определить локальную функцию в main
.
Можно заметить: а почему бы не модифицировать спецификацию friend-объявлений и не сказать, что неквалифицированные имена в определениях ссылаются на сущности в ближайшей охватывающей области видимости уровня namespace?
Я не вижу технических ограничений для такой реализации. С тем только замечанием, что это приведет к разной трактовке неквалифицированных имен во friend-объявлениях и во friend-определениях. Что некрасиво.
Актуальность этой темы, кстати, потенциально выросла с C++14, в котором локальные классы стали совсем не такими локальными, какими они были раньше
auto foo()
{
struct S
{
void bar() {}
};
return S();
}
int main()
{
auto a = foo();
a.bar();
decltype(a) b;
b.bar();
}
Я думаю, что проблема связана с тем, что friend-объявление не вводит объявленную функцию в область объявления. Функция является невидимой. Поэтому не имеет смысла определять friend-функцию в области объявления локального класса.
Когда же такое определение friend-функции встречается в нелокальном объявлении класса, то может подключаться зависящий от аргумента поиск (ADL), который рассматривает ассоциативные пространства имен и таким образом находит объявленную в классе функцию.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Вот про логику, как сделать сам MessageBox , я знаюВпихиваю код в деструктор:
Здравствуйте появилась проблема с поиском в документации информации :( А именно то, что я не нашел как поменять тип линии, ее цвет и как добавить...
Я хочу узнать как правильно добавить прокси к моему приложениюТак получилось, что сайт, который я парсю попал в реестр РКН, мне нужен способ...