Объявление локальной функции внутри пространства имен

В такой ситуации

namespace n {
    void f() {
        void another_function();
    }
}

Должна ли функция another_function быть определена внутри пространства имен n или вне его? VS 2012 (с ноябрьская CTP) говорит, что он должен быть снаружи, а GCC 4.7.2 на Mac говорит, что он должен быть внутри. Если я сделаю что-то неправильное, я получу неопределенные ошибки символов от компоновщиков.

Обычно я считаю, что GCC лучше соответствует стандарту, но это C++, и вы никогда не можете быть в этом уверены.


person Seth Carnegie    schedule 03.01.2013    source источник
comment
Почему вы хотите это сделать?   -  person Billy ONeal    schedule 03.01.2013
comment
@BillyONeal, потому что another_function — это деталь реализации, а f — это шаблон.   -  person Seth Carnegie    schedule 03.01.2013
comment
Но объявление another_function внутри f не делает его менее заметным, чем f. Это просто вызовет несколько ошибок определения, если кто-то определит свой собственный n::another_function.   -  person Billy ONeal    schedule 03.01.2013
comment
@BillyONeal ни один клиент не будет и не должен помещать вещи в мое пространство имен, поскольку это библиотека. Это делает его немного менее заметным, так как им нужно работать, чтобы получить прототип. Есть ли лучший способ сделать это?   -  person Seth Carnegie    schedule 03.01.2013
comment
Я бы просто поместил прототип внутрь your_namespace::detail. Во всяком случае, это то, что Boost делает в этих ситуациях. По соглашению все, что находится внутри пространства имен detail, является деталями реализации.   -  person Billy ONeal    schedule 03.01.2013


Ответы (2)


С++ 11 3.5 (а также С++ 03)

7 Если не обнаружено, что объявление области блока объекта со связью ссылается на какое-либо другое объявление, то этот объект является членом самого внутреннего объемлющего пространства имен. Однако такое объявление не вводит имя члена в область его пространства имен.

Объявление в вашем примере объявляет n::another_function.

person AnT    schedule 03.01.2013
comment
+1 - этот ответ более полный, чем мой. Оставив мой, потому что в нем все еще есть этот полезный пример. - person Billy ONeal; 03.01.2013

Согласно N3485 7.3.1 [namespace.def]/6, правильный ответ — n::another_function.

Включающие пространства имен объявления — это те пространства имен, в которых объявление лексически появляется, за исключением повторного объявления члена пространства имен вне его исходного пространства имен (например, определение, как указано в 7.3.1.2). Такое повторное объявление имеет те же объемлющие пространства имен, что и исходное объявление. [ Пример:

namespace Q {
    namespace V {
        void f(); // enclosing namespaces are the global namespace, Q, and Q::V
        class C { void m(); };
    }
    void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
        extern void h(); // ... so this declares Q::V::h
    }
    void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
    }
}

— конец примера]

person Billy ONeal    schedule 03.01.2013