В C ++ анонимное пространство имен эквивалентно:
namespace $$$$ {
//something
}
using namespace $$$$;
Где $$$$ — это какой-то уникальный идентификатор. В этом случае анонимное пространство имен полезно для кода, который не должен просматриваться вне модуля компиляции.
Пока все хорошо, однако недавно я начал писать некоторый код с шаблонами, такой код должен быть в заголовках, поэтому использование анонимных пространств имен не имеет большого смысла, так как простое включение заголовка сведет на нет эффект изоляции.
Тогда вопрос в том, что предлагается в этом случае? Я начал использовать именованное пространство имен Private. Это на самом деле не останавливает никого, кто хочет использовать идентификаторы внутри, но, по крайней мере, уменьшает столкновения имен с идентификатором «Private».
Есть ли лучшие способы? Предложения?
Придерживаться вашего Private
namespace
(или используйте более популярный detail
). Помните, что основная идея механизмов доступа C ++ состоит в том, что их трудно использовать неправильно, а не невозможно. Защитите себя от несчастных случаев, а не от злонамеренных атак.
Если вы отчаянно нуждаетесь в этой изоляции, почему бы не старый добрый файл?static
? Это было недооценено:
template <typename T>
static void foo()
{}
int main()
{
foo<char>();
}
Опять же, если вам нужно только foo
в пределах одной единицы перевода, то, вероятно, вы включаете ее только в заголовок внутри этой единицы перевода, и тогда не имеет значения, находится ли он «в заголовке». Так что просто не включайте шаблоны в другие единицы перевода, и вы уже в значительной степени достигли своей цели изоляции.
к действительно гарантировать изоляцию для все возможные экземпляры (т.е. те, которые вы создали в этом TU), используйте static
как указано выше, или просто задокументируйте свое намерение, используя detail
Пространство имен.
Самый обычный способ скрыть реализацию кода шаблона в заголовке — поместить реализацию в пространство имен detail
,
Например:
namespace cpputil { // my c++ utility library namespace
namespace detail { // implementation details of this libraries headers go here
// a functor private to the library
template<class T>
struct private_functor {
private_functor(const T& t) : _t(t) {}
void write(std::ostream& os) const { _t.write(os); }
private:
const T& _t;
};
// an extension to std::ostream::operator<<
template<class T>
std::ostream& operator<<(std::ostream& os, const private_functor<T>& pf)
{
pf.write(os);
return os;
}
}
/// a public template function that is designed to allow an object to be emitted to a stream
/// returns a function object that calls T::write(std::ostream&) when placed into an
/// output stream
template<class T>
detail::private_functor emit(const T& t) {
return detail::private_functor<T>(t);
}
}
// can be used like this:
int main() {
struct S {
void write(std::ostream& os) const { os << "{I am an S}"; }
};
std::cout << cpputil::emit(S) << std::endl;
return 0;
}