嵌套类是类模板中的依赖类型吗?

时间:2018-06-29 16:32:48

标签: c++ templates c++17 dependent-name

请考虑以下内容:

template<class> struct T
{
    struct T1
    {
        struct T2
        {

        };
    };
    /*typename*/ T1::T2 m;
};

如果没有typename,则编译将失败,因为T2被视为从属名称,因此不是类型。在考虑了C ++ 17草案标准(N4659)之后,我相信我已经确定了原因:

§17.6.2.1¶5

  

名称是当前实例的成员(如果它是
)   —一种无限定名称,当查找时,该名称指的是类的至少一个成员,该类是当前实例或其非依赖基类。
  ...
  名称是当前实例的依赖成员,如果它是当前实例的成员,则在查找时,该成员指的是类中至少一个成员是当前实例。

T1是当前实例的从属成员。 T2不是当前实例的成员(它是T1的成员),

§17.6.2.1¶9.3

  

如果类型是从属的,则是依赖的   ...
  —作为当前实例的从属成员的嵌套类或枚举,
  ...

T1是一个嵌套类,因此是一个依赖类型。

§17.6¶3

  

qualified-id 旨在引用不属于当前实例(17.6.2.1)及其 nested-name-specifier 成员的类型时指从属类型,它必须以关键字 typename 为前缀,形成一个 typename-specifier 。 ...

因此,typename是必需的。

我的理解正确吗?如果是这样,这背后的原理是什么? T1::T2的查找如何找到嵌套在T1中的T2以外的任何东西?

1 个答案:

答案 0 :(得分:4)

是的,您是正确的。

对于您而言,这并不重要,因为如果不实例化T1(因为它是类成员),就不可能专门化m。但是您可以这样做,将m放在函数中:

template<class> struct T
{
    struct T1
    {
        struct T2
        {

        };
    };

    void foo() {
        typename T1::T2 m;
    }
};

template<>
struct T<void>::T1 {
    int T2;
};

如果T1不依赖,则您的代码可能会更改含义,因为T2将引用值而不是类型。