位置实用程序例程与使用类型相同的命名空间



我有一堆我自己的对象,这些对象已尽职尽责地放入自己的名称空间中:

namespace my { struct foo final {}; /* etc. */}

我应该在哪里放置非成员的非朋友功能(即"全局"实用程序),将我的类型作为参数?我还应该把它们放在my名称空间

namespace my { extern void f(const foo&); }

或,是否有上行(或下行)将它们放在全局名称空间中

extern void f(const my::foo&);

无论哪种情况,f的参数都是my::foo,因此该功能本身实际上是命名为::f()还是my::f()

编辑:请注意,我专门不是寻找"我喜欢全局"或"我喜欢命名空间中的我喜欢"(或类似)。相反,我正在寻求具体的技术原因,而不是一种方法,而不是另一种方法(假设实际上存在这种差异)。从评论中,听起来像是一个(?)因素可能是ADL行为。还有其他吗?

将操作紧密耦合到与类型允许参数依赖查找或koenig查找的类型相同的类型。

污染全球名称空间通常是一个坏主意。您只会获得一个全局名称空间,如果您的代码不使用其他人放置的内容,则很少有解决方案。

例如,如果您在全局名称空间中具有名为CString的类型或功能,并且尝试包括并使用MFC代码,将CString注射到全局名称空间中,则将您拧紧。

将代码放在namespace中表示您用一个令牌污染全局名称空间,而不是每个功能和键入名称(etc)。

要考虑的第二件事是,如果您的类型是template生成的,则将friend函数放置在template中会导致可见的非template函数,当与模板的类实例进行交互时,可以找到该功能。

namespace my {
  template<class T>
  struct foo {
    friend foo operator+( foo lhs, foo rhs ) { return {lhs.x+rhs.x}; }
    friend foo add( foo lhs, foo rhs ) { return {lhs.x+rhs.x}; }
    int x;
  };
}

现在my::foo f0{0},f1{1}; auto f2 = add(f0, f1);auto f3=f0+f1;

addoperator+都不是模板,这意味着如果我们有转换为foo的类型,add(f0, converts_to_foo)也可以工作。

它取决于。有时,您有一个函数,该函数从无关的名称空间(例如在I/O或序列化中)中获取两个参数,它可以驻留在其中任何一个(但不在全局名称空间中!)

中。
// foo can be either in N1 or N2, but not in global
namespace N1 { auto foo(A&, N2::B const&) }
namespace N2 { auto foo(N1::A&, B const&) } 

或者您有一种应该用于通用参数(例如输入和输出范围)的算法,您将把该函数放在其自己的命名空间

// algo should probably be in its own namespace N
namespace N {
    template<class R1, class R2>
    auto algo(R1 const& in, R2& out)
}

呼叫这种算法最好而不依赖ADL,即 N::algo(rin, rout)

最新更新