如果我在标题中需要匿名命名空间怎么办?

时间:2014-09-30 10:02:27

标签: c++ namespaces header-files anonymous

在C ++中,匿名命名空间等同于:

namespace $$$$ {
  //something
}
using namespace $$$$;

其中$$$$是某种唯一标识符。然后,匿名命名空间对于不应在编译单元外看到的代码很有用。

到目前为止一直很好,但是最近我开始用模板编写一些代码,这样的代码必须在头文件中,因此使用匿名命名空间没有多大意义,因为仅仅包含头部会使隔离效果无效。

然后问题是,在这种情况下建议的方式是什么?我开始使用名为Private的命名空间。它并没有真正阻止任何想要在其中使用标识符的人,但至少它将名称冲突减少为id“Private”。

有更好的方法吗?建议?

3 个答案:

答案 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;
}