全球友元函数

问题描述:

的提前声明我有以下的命名空间和类层次结构:全球友元函数

namespace Ns1 { 
    class Outer { 
    private: 
      class Inner { 
      }; 
      QSet<Inner> set; 
    }; 
} 

现在我需要声明一个全局函数:

uint qHash(Ns1::Outer::Inner const& el); 
bool operator==(Ns1::Outer::Inner const& el1, 
       Ns1::Outer::Inner const& el); 

因此函数必须是一个朋友到外和内在。 的问题,并表明该功能是在全球范围内:

friend uint qHash(Ns1::Outer::Inner const& el); 
friend operator==(Ns1::Outer::Inner const& el1, 
       Ns1::Outer::Inner const& el); 

我不能处理这种情况的前置声明。任何解决方案

+4

为什么这个功能需要是一个“全局”功能?我认为问题本身就在这里。如果它可以接受的参数是'Ns1 :: Outer :: Inner',那么在命名空间'Ns1'之外我没有看到任何要点。鉴于'Inner'是'private'到'Outer',我也没有看到任何使它成为非成员函数的观点。 – Nawaz 2013-02-27 14:58:40

+0

Plz。问题是我说的问题。不要让你个人的假设。如果存在,请给出解决方案。 – user14416 2013-02-27 15:00:42

+0

如果'Inner'是私有的,你希望如何获得一个'Inner'对象来将它传递给函数?这看起来像一个设计问题 - 就像'friend'的许多用法一样。不,你不需要'f'成为'Inner'的朋友 - 除非它使用私有/受保护的方法。 – 2013-02-27 15:01:03

编辑:

你是对的!你已经找到了这种语言无法处理的特殊情况(因为friend船只声明只适用于之前声明的函数,或者适用于最内层的名称空间)。不幸的是,这意味着你将不得不稍微重构你的代码,因为你想做的事情不能完全按照这种方式完成。

最简单的方法是在Ns1命名空间中定义这两个函数,然后在using中定义它们到全局命名空间中。除了嵌套命名空间中有两个额外的函数之外,这基本上与您想要的效果基本相同。

你的其他选择涉及到从根本上解决问题:为什么你的类对象的公共接口不能提供足够的能力以至于需要友谊?例如,如果您打算在全局范围内传递Inner对象,为什么InnerOuter内保密?

为什么散列函数和比较函数需要访问Inner的内部状态? Inner为什么不提供一个公共的比较界面,然后由操作员使用?

+1

实际上这并不能解决它,因为显然如果你使用::来限定它们的功能,就必须声明这些函数。而且你不能转发他们,因为他们的签名需要Outer的完整定义。看起来像一个语言缺陷。 – user1610015 2013-02-27 16:26:52

+0

是的,这个答案不能解决问题。 – user14416 2013-02-27 16:29:00