嵌套在其他任何类别中的已知类名称的C ++模板朋友声明

问题描述

晚上好。

在编写一些通用代码(至少在C ++ 11中)时,我遇到以下问题:

考虑一个名为I的类,该类可以嵌套在各种类A,B,...,N中:

class A
{
protected:
  friend class I;
  class I
  {
  } i;
};

class B
{
protected:
  friend class I;
  class I
  {
  } i;
};

etc.

实际上I是一种界面工具,会自动插入各种用户类A ... N中。不在乎这样做的原因...

然后有一个特定的类Z,目标是将任何I声明为Z的朋友,以便任何I和其他任何对象都不能使用Z,无论类A ... N( I将嵌套在其中。

如果我这样声明:

class Z
{
  friend class A;   // <--- but I don't want to have to kNow this one
  friend class I;
private:            // creation and use of Z are restricted to tools like I
  Z();
  // other methods
};

然后它仅适用于A::I

可以从A::I::some_function()构建和使用Z, 但不是B::I或B ... N中的其他任何源。

没有friend class A;I都无法访问Z。

  • 如何使其具有通用性?

我正在寻找一种写模板朋友声明的方法,以声明对任何X::I的访问权限,其中X是模板参数。

当然不是I的模板参数,因为I不是模板。

当然,我不想授予对任何类X的访问权限,以便任何X::I也可以访问Z!

以下内容无效:

class Z
{
  template< class X>  friend class X::I;
  ...
};

=>错误:“我”不是“ X”的成员
从gcc版本5.4.0 20160609(Ubuntu 5.4.0-6ubuntu1〜16.04.11)

对正确语法有任何想法吗?我没有在参考文献中找到该用例...

非常感谢, 此致。

==================已在8月16日添加:精度:

I持久地作为A(或其他)的一部分而存在,而Z是仅在I的特定操作期间有效的工具,可能重复一次,然后创建一个新的Z,使用它,然后每次都将其删除I方法的局部变量。

此外,Z一个有效载荷,因此我不想使其成为嵌入I的每个对象的永久部分。例如,通过使Z继承I

解决方法

通过使I继承Z,并使Z成为抽象基类(因此不能直接访问),可能可以实现您想要的目标。

类似于:

class Z
{
    virtual void __() = 0;
  public:
    virtual ~Z() = default;
    void method() { std::cout << "Method from Z" << std::endl; }
};

class A
{
    friend class I;
  
  public:
    class I : public Z
    {
        void __() final {}
      public:
        static Z *make_z();
    } i;
};

Z *A::I::make_z()
{
    return new I();
}

int main()
{
    Z *z = A::I::make_z();
    z->method();
    
    return 0;
}