【问题标题】:Making a class or struct to be friend of all template instantiated class?让一个类或结构成为所有模板实例化类的朋友?
【发布时间】:2017-03-01 17:43:26
【问题描述】:
#include <iostream>

using namespace std;

struct s1;

template <typename... type>
class Base : public type::inner...
{
    friend struct s1;

};

struct Test;

struct s1
{
    template <typename... type>
    friend class Base;

    friend class Test;

    private:
    struct inner {

    int member1;
    int member2;
    };
};

struct s2
{
    struct inner {

    int member3;
    int member4;
    };
};

struct Test : public s1::inner, public s2::inner
{

};

int main()
{
    Base<s1, s2> base;
    base.member1 = 0;

    Test t;
    t.member3 = 22;

    cout << "Hello world!" << endl;
    return 0;
}

当我尝试编译上述代码时,出现以下错误

在“类 Base”的实例化中: 错误:'struct s1::inner' 是私有的

但是,当尝试通过注释掉基变量来编译此程序时,类 Test 编译成功且没有错误。我想让名为 Base 的模板类成为 struct s1 的朋友。我该怎么做?

【问题讨论】:

  • 我注意到您正在声明类 Test 和交友类 test,但 Test 是一个结构。这是故意的吗?
  • “但是Test类编译成功没有错误。”什么意思?我怀疑编译器在抱怨 Test 之前停止了。
  • @tramstheman 这是一个错字。对不起。 πάντα ῥεῖ 我尝试通过注释掉基本变量来编译测试。这样就编译成功了。将更新问题
  • g++ 扼流圈,clang++ 吞咽。
  • 我刚刚运行了您发布的代码,它编译并运行良好。你用的是什么编译器?

标签: c++ c++11 templates


【解决方案1】:

这里有一个解决这个奇怪问题的方法...

使用继承内部结构的嵌套结构创建结构:

template <class... Types>
struct BaseInherit {
  struct Inner : public Types::Inner... {};
};

然后,继承 BaseInherit 在 Base 中的嵌套内部:

template <class... Types>
class Base : public BaseInherit <Types...>::Inner {};

这就是我必须为 GCC (6.3.1) 做的事情。

编辑:忘了说你会添加 BaseInherit 作为友元结构,而不是 Base。示例:

class S1 {

  template <class... Types>
  friend struct BaseInherit;

  struct Inner { int member1, member2; };

};

编辑:如何找到解决方法 - 我试图找出编译器在继承时推断可变参数模板的顺序。由于它在直接继承它们时抱怨,我认为它可能在类的范围内工作。当然,我们不能从它自己的嵌套结构中继承,所以我们把它放在另一个结构/公共类的嵌套结构中。

【讨论】:

  • 我会检查这个。但是在您给出的代码中,名为“Inner”的类不是私有的。对我来说,这是我的要求。
  • @PremkumarU 为什么 Inner 类应该是私有的?您自己的模板类也从那些私有内部类公开继承...
  • @ben 您的解决方法有效。我真的很想知道您是如何找到这种解决方法的。我很高兴接受这个作为我的答案和奖励。但如果可能的话,您能否解释一下您是如何找到这种解决方法的?谢谢
  • @Aconcagua 我希望内部结构成为类模板的一部分,同时不需要从我的库中访问内部结构。这就是为什么我将它设为私有并且可以从类模板访问,因为朋友声明。还有其他比我的方法更好的替代设计吗?
  • @PremkumarU 我不太确定如果你想直接继承还能做什么。我注意到您从 Base 公开继承,所以我认为这适用于您的示例。另一种将 BaseInherit 隐藏为实现细节的方法是将其放在匿名命名空间中。我还将更新答案以解释我是如何解决的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多