Как правильно ссылаться на функцию в анонимном пространстве имен
Рассмотрим этот фрагмент кода С++:
namespace
{
void f()
{
}
class A
{
void f()
{
::f(); // VC++: error C2039: 'f' : is not a member of '`global namespace''
}
};
}
GCC компилирует это просто отлично. Visual С++ 2008 не удается скомпилировать ошибку C2039. Какой из этих двух компиляторов прав здесь? Есть ли способ правильно ссылаться на этот "глобальный" f
?
Изменить: Зак предложил попробовать, и он работает с обоими компиляторами. Мне немного странно.
namespace
{
void f()
{
}
class A
{
void f();
};
}
void A::f()
{
::f();
}
Ответы
Ответ 1
VС++ 2008 здесь не так. Согласно стандарту С++ 03 3.4.3.4:
Имя, предваряемое унарной областью оператор:: (5.1) просматривается в глобальный охват, в блоке перевода где он используется. Имя должно быть объявляется в глобальной области пространства имен или это имя, чья декларация видимый в глобальном масштабе из-за с использованием директивы (3.4.3.2). Использование:: позволяет глобальное имя упоминается, даже если его идентификатор имеет были скрыты (3.3.7).
Важная часть здесь состоит в том, что директива using в глобальном пространстве имен сделает эти символы доступными с оператором области видимости.
И согласно 7.3.1.1/1 анонимное пространство имен эквивалентно:
namespace *unique* { /* empty body */ }
using namespace *unique*;
namespace *unique* { namespace-body }
Таким образом, между этими двумя разделами автономная функция должна быть доступна в глобальном пространстве имен.
Ответ 2
Как отметил академик Robot, Visual С++ ошибочен. В качестве обходного пути добавление пустого безымянного блока пространства имен должно устранить проблему (у меня нет Visual С++ 2008 для тестирования, но это работает в Visual С++ 2010):
// empty unnamed namespace to placate compiler
namespace { }
namespace {
void f() { }
struct A {
void f() { ::f(); }
};
}
Я сообщил об этой проблеме команде Visual С++.