首页 > 解决方案 > 已知类名的 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,目标是将 any 声明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::IB...N 中的任何其他地方构建和使用。

没有friend class A;,没有一个I可以访问 Z。

我正在寻找一种编写模板友元声明的方法,以授予对X::IX 是模板参数的任何地方的访问权限。

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

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

以下不起作用:

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

=> 错误:'I' 不是
来自 gcc 版本 5.4.0 20160609 的 'X' 的成员(Ubuntu 5.4.0-6ubuntu1~16.04.11)

知道正确的语法吗?我没有在参考文献中找到那个用例......

非常感谢,亲切的问候。

================= 于 8 月 16 日添加: 精度:

I持久存在作为A(或其他)的一部分,而是Z仅在 的特定操作期间存在的工具I,可以重复,然后Z创建一个新的,使用然后删除每次作为方法的本地I

还有Z一个随之而来的有效负载,我不想让它成为每个嵌入I. 例如,通过Z继承I.

标签: c++templatesinner-classesfriend

解决方案


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;
}

推荐阅读