Как скрыть шаблонную функцию, не являющуюся членом, из кода клиента?

У меня есть функции шаблона, скажем,

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.
Может кто-нибудь объяснить, почему он компилируется с использованием директивы, но не с квалифицированными именами, и есть ли лучший способ добиться того, чего я хочу?

4

Решение

Обычная идиома для этого — создать пространство имен «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, чтобы найти любую доступную функцию, которая соответствует.

6

Другие решения

Я провел еще несколько тестов, на самом деле, в более поздней версии gcc (Ubuntu / Linaro 4.6.3-1ubuntu5) и -std = c ++ 0x, он делает именно то, что я ожидал.

В главном файле ни директива using, ни квалифицированное имя не позволят вам вызвать функцию внутри анонимного пространства имен, которое само находится внутри другого пространства имен.

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

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

0

По вопросам рекламы [email protected]