如果我需要在标头中使用未命名的命名空间怎么办?

问题描述 投票:0回答:3

在 C++ 中,未命名的命名空间相当于:

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

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

到目前为止还不错,但是最近我开始用模板编写一些代码,这些代码必须位于标头中,因此使用未命名的命名空间没有多大意义,因为仅仅包含标头就会使隔离效果失效。

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

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

c++ namespaces header-files unnamed-namespace
3个回答
5
投票

坚持使用您的

Private
namespace
(或使用更流行的
detail
)。请记住,C++ 访问机制背后的主要思想是使滥用它们变得困难,而不是不可能。保护自己免受意外事故,而不是恶意攻击。


5
投票

如果您渴望这种隔离,为什么不使用旧的好文件-

static
?它未被弃用:

template <typename T>
static void foo()
{}

int main()
{
    foo<char>();
}

话又说回来,如果您只需要在一个翻译单元内使用

foo
,那么您可能只将其包含在该翻译单元内的标头中,然后无论它是否“在标头中”都无关紧要。因此,只需不要将模板包含在其他翻译单元中,您就已经基本上实现了隔离的目标。

为了真正保证所有可能的实例化(即包括您在本TU中创建的实例)的隔离,请如上所述使用

static
或仅使用
detail
命名空间记录您的意图。


1
投票

在标头中隐藏模板代码实现的最常用方法是将实现放入名为

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.