【问题标题】:Defining a static data member of a templated class within a templated class在模板类中定义模板类的静态数据成员
【发布时间】:2017-10-04 21:46:03
【问题描述】:

我在另一个类模板中有一个类模板。内部类有一个静态数据成员。我正在努力为它提供一个定义。以下示例适用于 clang 3.8,但不适用于 gcc-7.1

template <typename T>
struct Out {
  template <typename U>
  struct In {
    static int var;
  };
};

template <typename T>
template <typename U>
int Out<T>::template In<U>::var;

gcc 给出错误:

error: template definition of non-template ‘int Out<T>::In<U>::var’
 int Out<T>::template In<U>::var;
                             ^~~

我该怎么做才能让 gcc 开心?


编辑:原来摆脱 template 使这项工作:

template <typename T>
template <typename U>
int Out<T>::In<U>::var;

还有一个问题,template 这里是否允许?

【问题讨论】:

  • 不仅允许,而且需要。此时,编译器不知道 Out::In 是否是类型名/成员/模板。它会猜测成员,并猜测您首先要在 ::,这是一个错误。如上所述,较新的 gcc 在此处提供有用的诊断;以前,情况更糟。
  • @lorro 我认为这是必要的,因为你给出的原因。我的困惑得到了证实

标签: c++ templates c++14


【解决方案1】:

In 之前没有template 的情况下,这种类型的定义更常见。这里不需要template 关键字,因为Out&lt;T&gt;::In 是“当前专业化的成员”。

有关指定何时在成员名称之前需要 template 关键字的规则,请参阅 [temp.names]/4。技术术语“当前专业化成员”的定义见[temp.dep.type]/4。

但实际上这里允许使用关键字,因为语法允许在任何 :: 和名称之间使用它,并且语义只要求后面的名称与模板参数一起使用或命名一个类模板([temp. names]/5),并且标准中没有其他规则禁止它。正如 [temp.names]/5 中的注释所解释的:

[ 注意:typename 前缀的情况一样,template 前缀在并非绝对必要的情况下是允许的;即,当 nested-name-specifier-&gt;. 左侧的表达式不依赖于模板参数,或使用未出现在模板。 - 尾注]

【讨论】:

  • template 被省略时,为什么它不会将In 视为Out 的静态数据成员,我仍然感到困惑
  • C++11 中关于允许冗余template 消歧器的规则发生了变化。特别是关于“使用未出现在模板范围内”的部分。
猜你喜欢
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多