在C ++中,匿名命名空间等同于:
namespace $$$$ {
//something
}
using namespace $$$$;
其中$$$$是某种唯一标识符。然后,匿名命名空间对于不应在编译单元外看到的代码很有用。
到目前为止一直很好,但是最近我开始用模板编写一些代码,这样的代码必须在头文件中,因此使用匿名命名空间没有多大意义,因为仅仅包含头部会使隔离效果无效。
然后问题是,在这种情况下建议的方式是什么?我开始使用名为Private的命名空间。它并没有真正阻止任何想要在其中使用标识符的人,但至少它将名称冲突减少为id“Private”。
有更好的方法吗?建议?
答案 0 :(得分:4)
如果你对这种隔离感到绝望,为什么不能找到好的旧文件 - static
?它没有被证实:
template <typename T>
static void foo()
{}
int main()
{
foo<char>();
}
然后,如果你只需要在一个翻译单元中foo
,那么大概你只是将它包含在该翻译单元的标题中,然后无论它是否在“标题中”都无关紧要”。因此,只是不要将模板包含在其他翻译单元中,并且您已基本实现了隔离目标。
要确实保证所有可能实例化的隔离(即包括您在此TU中创建的实例),请使用上面的static
或仅仅是文档您使用detail
命名空间的意图。
答案 1 :(得分:3)
坚持使用Private
namespace
(或使用更受欢迎的detail
)。请记住,C ++访问机制背后的主要思想是难以滥用它们,而不是不可能。保护自己免受意外事故,而不是恶意攻击。
答案 2 :(得分:0)
在标头中隐藏模板代码实现的最常用方法是将实现放入名为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;
}