У меня есть функции шаблона, скажем,
template<class T>
void mysort(std::vector<T>& vec)
{
size_t b, m, e,
...
mysort(vec, b, m, e);
}
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)
{
size_t x, y, z;
...
mysort (vec, x, y, z);
}
Публичный интерфейс — это только ссылка на вектор. Я хотел бы скрыть другую, реализацию, так что ни один клиентский код не может сделать
mysort(vec, a, b, c);
Неправильно создавать класс и делать частную статическую функцию реализации, я пытаюсь использовать анонимное пространство имен,
namespace abc
{
namespace
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
template<class T>
void mysort(std::vector<T>& vec)...
}
Это помогает, но не совсем нокаут …
#include "mysort.h"
int main()
{
...
abc::mysort(vec, a, b, c); // this won't compile, good
}
однако, если я изменю это на:
#include "mysort.h"
using namespace abc;
int main()
{
...
mysort(vec, a, b, c); // it compiles and runs!!
}
Я использую gcc Ubuntu 4.4.3-4ubuntu5 на x86_64.
Может кто-нибудь объяснить, почему он компилируется с использованием директивы, но не с квалифицированными именами, и есть ли лучший способ добиться того, чего я хочу?
Обычная идиома для этого — создать пространство имен «detail», которое предназначено только для внутреннего кода:
namespace abc
{
namespace detail
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
template<class T>
void mysort(std::vector<T>& vec)...
}
Чтобы ответить на ваш вопрос о поведении безымянного пространства имен:
Неназванные пространства имен (они не называются анонимными пространствами имен) называются немного странными — они вам не называются, но компилятор фактически генерирует для них уникальное внутреннее имя. Ваш пример эквивалентен:
namespace abc
{
namespace def // lets say 'def' is unique.
{
template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
}
using namespace def;
template<class T>
void mysort(std::vector<T>& vec)...
}
Вы заметите, что он ведет себя так же, как ваш безымянный пример: вы не можете сделать abc::mysort(vec, 1, 2, 3)
здесь, но вы можете using namespace abc; mysort(vec, 1, 2, 3)
,
Это происходит потому, что нет двух abc::mysort
с, только abc::def::mysort
а также abc::mysort
, Когда вы объявили фактический abc::mysort
скрывает тот, что принес using namespace def
, Обратите внимание, если вы закомментируете 1-param mysort
можно сказать abc::mysort(vec, 1, 2, 3)
,
Поскольку это было скрыто, квалифицированный вызов abc::mysort
надо смотреть явно abc::mysort
и находит только версию с 1 параметром.
Тем не менее, с неквалифицированным вызовом через using namespace abc; mysort(vec, 1, 2, 3)
, он может использовать ADL, чтобы найти любую доступную функцию, которая соответствует.
Я провел еще несколько тестов, на самом деле, в более поздней версии gcc (Ubuntu / Linaro 4.6.3-1ubuntu5) и -std = c ++ 0x, он делает именно то, что я ожидал.
В главном файле ни директива using, ни квалифицированное имя не позволят вам вызвать функцию внутри анонимного пространства имен, которое само находится внутри другого пространства имен.
Я думаю, причина в том, что компилятор подтверждает последний стандарт, который говорит, что у безымянного пространства имен по умолчанию есть внутренняя связь.
Мне кажется, подход безымянного пространства имен следует отдавать предпочтение старой практике «подробно» с пространством имен.