在模板类中定义模板类的静态数据成员

问题描述:

我在另一个类模板中有一个类模板。内部类有一个静态数据成员。我正在努力为它提供一个定义。下面的例子作品在铛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允许在这里?

+0

不仅允许,而且还需要。此时,编译器不知道是否Out :: In是一个typename /成员/模板。它会猜测成员,并猜测你想要在 ::,这是一个错误。较新的gccs,如上所述,在这里提供有用的诊断;之前,情况更糟。 – lorro

+1

@lorro我认为这是必要的,你给的理由。我的困惑得到了证实 –

In之前没有template这种类型的定义将更常见。此处不需要template关键字,因为Out<T>::In是“当前专业化的成员”。

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

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

[ Note: As is the case with the typename prefix, the template prefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the -> or . is not dependent on a template parameter, or the use does not appear in the scope of a template. - end note]

+0

当我省略'template'作为'Out'的静态数据成员时,我仍然感到困惑 –

+0

允许多余'template'消歧器被允许改变的规则C++ 11。具体而言,“使用的部分不出现在模板范围内”。 – Oktalist