【问题标题】:declare class template as friend将类模板声明为朋友
【发布时间】:2011-10-26 08:23:31
【问题描述】:

由于某些原因,我想写这样的代码:

template<class T>
class C : public T
{
friend class T;
};

我认为代码很清楚。我想要一个类模板,它定义一个派生自作为模板参数传递给它的类的类,并且为了使事情更复杂一点,我想将基类定义为派生类的朋友。 MSVC 编译器的代码似乎没问题,但 GNU C++ 编译器抱怨很多。我应该怎么做才能拥有所需的功能?

【问题讨论】:

  • 如果你是从它派生的,为什么要交朋友?
  • GCC 具体说了什么?
  • @Nim:例如,您可能正在使用 CRTP 来实现模拟动态绑定,并且您想要一个私有虚拟函数的等价物。也就是说,从基类调用但不需要是class C的公共接口的一部分的函数。你可以说,“好吧,它不需要是私有的,只是不允许公众使用它”,这是真的,但是当你告诉他们时,有些人会非常激动(除了禁用默认副本) C++ 中的访问修饰符完全是浪费时间,您应该始终公开所有内容;-)
  • @Nim:我想使用 Steve Jessop 提到的 CRTP。
  • @OliCharlesworth:它抱怨朋友关键字使用不正确,比如缺少类键。

标签: c++ templates friend


【解决方案1】:

它格式不正确,并且不是有效的 C++,尽管它在 MSVC 中工作。 C++03 标准是这样说的(7.1.5.3 §2):

3.4.4 描述了如何在详细类型说明符中对标识符进行名称查找。如果标识符解析为类名 或 enum-name,详细类型说明符将其引入 声明的方式与简单类型说明符引入它的方式相同 类型名称。如果标识符解析为 typedef-name 或模板 类型参数,详细说明的类型说明符格式不正确。 [笔记: 这意味着,在带有模板的类模板中 类型参数T,声明

       friend class T;

格式不正确。 ] 如果名称查找没有找到 名称,详细类型说明符格式不正确,除非它属于 简单形式的类键标识符,在这种情况下,标识符是 如 3.3.1 所述声明。

出于同样的原因,您也不能执行friend class std::string; 之类的操作,但您必须使用模板参数与std::basic_string 成为朋友。

但是,新的 C++11 规范允许使用新语法来声明朋友,即(N3242 的 11.3 §3):

friend <typename-specifier>;

这种新语法允许你做你想做的事(虽然我不知道 MSVC 是否支持这个):

template<typename T>
class C : public T
{
    friend T;
};

【讨论】:

    猜你喜欢
    • 2017-02-09
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 2019-09-15
    相关资源
    最近更新 更多