模板参数列表中的额外typename关键字:它是否有效?

Con*_*tor 5 c++ templates typename c++11 c++14

以下代码使用C++ 03(标志),C++ 11(标志)C++ 14(标志)下的clang 3.5.0g ++ 4.9.0(带-Wall -Wextra -pedantic-errors标志)成功编译:-std=C++03-std=C++11-std=C++14

namespace N
{
    typedef int T;

    enum E{};
}

template <typename N::T>
struct ST{};

template <typename N::E>
struct SE{};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

typename在非类型模板参数声明之前添加额外关键字是否有效?


请注意,以下代码无法编译(如C++ 03,C++ 11C++ 14代码):

typedef int T;

enum E{};

template <typename T t>
struct ST{};

template <typename E e>
struct SE{};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

但是下面的一个编译好了(C++ 03,C++ 11C++ 14):

typedef int T;

enum E{};

template <typename ::T>
struct ST{};

template <typename ::E>
struct SE{};

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 6

允许,但只能使用合格的名称:

typename-specifier:
          typename nested-name-specifier标识符
          typename nested-name-specifier templateopt simple-template-id

因此typename E根据语法是错误的.typename N::E因为这个名字是合格的.第三种情况,typename ::E很好,因为它::是一个有效的嵌套名称说明符.

C++ 03标准在[temp.res]/5中指定

该关键字typename只应用于限定名称,但这些名称不必相关.

C++ 11标准明确说明了这一点,但在[temp.names]/5中的注释中:

[ 注意:typename前缀的情况一样,在template 不是绝对必要的情况下允许使用前缀; 即,当嵌套名称说明符或在左侧的表达 ->.上的不依赖模板的参数,或使用未出现在模板的范围.- 结束说明 ]

相同的注释存在于C++ 14标准的完全相同的位置.