Поиск имени функции друга в локальном классе

Компиляция следующего:

void bar() { /* ... */ }

void foo()
{
    struct MyStruct
    {
        friend void bar();
    };
}

int main()
{
    //..
}

приводит к ошибке:

ошибка: объявление друга 'void bar()' в локальном классе без предварительного объявления

Почему поиск имени не работает? Как я могу это исправить?


person user1086635    schedule 03.01.2012    source источник
comment
При работе с ошибкой рекомендуется опубликовать точное сообщение об ошибке. Это помогает другим людям с такой же проблемой найти ваш вопрос.   -  person outis    schedule 04.01.2012
comment
Пожалуйста, обновите вопрос с сообщением об ошибке. Как правило, отвечайте на запросы о разъяснениях, обновляя свой пост, а не отвечая комментарием. Во-первых, вопрос должен быть понятен без чтения комментариев. С другой стороны, SO — это QA и сайт, а не форум, и комментарии не предназначены (и не подходят) для дискуссий.   -  person outis    schedule 04.01.2012


Ответы (1)


Вы не можете получить доступ к локальному классу за его охватывающей областью, даже если вы дружите, потому что The name of a local class is local to its enclosing scope - §9.8/1.


Однако, если вы просто хотите, чтобы он скомпилировался, явно скажите, что он выглядит в глобальной области видимости...

friend void ::bar();

* Это исправляет это в VS, но не в GCC по какой-то причине.

§11.3/11 (спасибо, Джок)

Если объявление друга появляется в локальном классе (9.8) и указанное имя является неполным именем, предыдущее объявление просматривается без учета областей, которые находятся за пределами самой внутренней охватывающей области, не относящейся к классу.

person David    schedule 03.01.2012
comment
Это тоже было моей мыслью, но она не работает с той же ошибкой (GCC 4.6.1) - person jrok; 04.01.2012
comment
Это исправлено в VS2010; исходное предупреждение в VS2010 было: warning C4813: 'bar' : a friend function of a local class must have been previously declared - person David; 04.01.2012
comment
В §9.8/1 также говорится: Объявления в локальном классе могут использовать только имена типов, статические переменные, внешние переменные и функции, а также перечислители из объемлющей области. Я все еще не уверен, что ::bar() правильно . - person jrok; 04.01.2012