【问题标题】:What if I need anonymous namespace in a header?如果我在标头中需要匿名命名空间怎么办?
【发布时间】:2014-09-30 10:02:27
【问题描述】:

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

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

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

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

那么问题是,在这种情况下建议的方法是什么?我开始使用一个名为 Private 的命名空间。它并没有真正阻止任何想要使用内部标识符的人,但至少它减少了名称冲突到 id “Private”。

还有更好的方法吗?有什么建议吗?

【问题讨论】:

  • AFAIK 这就是你所能做的,模板库经常为此目的使用命名空间,例如detail
  • 理想情况下,您的所有代码都应该在某种命名空间中。将您的模板放入名为 Utility、Alpha 或 MyWork 之类的命名空间中。并将帮助功能也放在那里。
  • 感谢 user657267;那是我正在寻找的确认。我害怕我错过了显而易见的事情。

标签: c++ namespaces header-files anonymous


【解决方案1】:

坚持使用您的Privatenamespace(或使用更受欢迎的detail)。请记住,C++ 访问机制背后的主要思想是使滥用它们变得困难,而不是不可能。保护自己免受意外伤害,而不是恶意攻击。

【讨论】:

    【解决方案2】:

    如果您迫切需要这种隔离,为什么不使用旧文件-static?它未被弃用:

    template <typename T>
    static void foo()
    {}
    
    int main()
    {
        foo<char>();
    }
    

    再一次,如果您只需要在一个翻译单元中foo,那么大概您只是将它包含在该翻译单元的标题中,然后它是否“在标题中”都没有关系。因此,只需不要将模板包含在其他翻译单元中,您就已经在很大程度上实现了隔离目标。

    为了真正保证对所有可能的实例化(即包括您在本 TU 中创建的实例化)进行隔离,如上所述使用static 或简单地记录您的意图使用 detail 命名空间。

    【讨论】:

    • +1:如果您想在多个 TU 中使用模板,则只需在标头中即可。
    【解决方案3】:

    在标头中隐藏模板代码实现的最常用方法是将实现放入名为 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-23
      • 1970-01-01
      • 1970-01-01
      • 2010-09-26
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多