Как правильно ссылаться на функцию в анонимном пространстве имен - PullRequest
20 голосов
/ 31 марта 2011

Рассмотрим этот фрагмент кода C ++:

namespace
{
    void f()
    {
    }

    class A
    {
        void f()
        {
            ::f(); // VC++: error C2039: 'f' : is not a member of '`global namespace''
        }
    };
}

GCC компилирует это просто отлично.Visual C ++ 2008 не может скомпилировать, выплевывая ошибку C2039.Какой из этих двух компиляторов правильный?Есть ли способ сослаться на то, что "global" f правильно?

Edit: Zack предложил попробовать, и это работает с обоими компиляторами.Выглядит немного странно для меня.

namespace
{
    void f()
    {
    }

    class A
    {
        void f();
    };
}

void A::f()
{
    ::f();
}

Ответы [ 2 ]

9 голосов
/ 31 марта 2011

VC ++ 2008 здесь не так. Согласно стандарту c ++ 03 3.4.3.4:

Имя с префиксом одинарной области видимости оператор :: (5.1) ищется в глобальный охват, в переводческом блоке где это используется. Имя должно быть объявлено в глобальной области имен пространства или должно быть имя, объявление которого видимый в глобальном масштабе из-за директива using (3.4.3.2). Использование :: позволяет глобальному имени быть упоминается, даже если его идентификатор имеет был скрыт (3.3.7).

Важной частью здесь является то, что директива using в глобальном пространстве имен сделает эти символы доступными с помощью оператора scope.

А согласно 7.3.1.1/1 анонимное пространство имен эквивалентно:

namespace *unique* { /* empty body */ }
using namespace *unique*;
namespace *unique* { namespace-body }

Таким образом, между этими двумя разделами автономная функция должна быть доступна в глобальном пространстве имен.

7 голосов
/ 31 марта 2011

Как указывает acadeRobot, Visual C ++ не так.В качестве обходного пути, добавление пустого безымянного блока пространства имен должно решить проблему (у меня нет Visual C ++ 2008 для тестирования, но это работает в Visual C ++ 2010):

// empty unnamed namespace to placate compiler
namespace { }

namespace {
    void f() { }
    struct A {
        void f() { ::f(); }
    };
}

Я сообщил о проблемев команду Visual C ++.

...