以下代码使用C++03 (flag -std=C++03
)下的 clang 3.5.0 和 g ++ 4.9.0 (带有-Wall -Wextra -pedantic-errors
标记)成功编译,{{ 3}}和C++11 (flag -std=C++11
):
namespace N
{
typedef int T;
enum E{};
}
template <typename N::T>
struct ST{};
template <typename N::E>
struct SE{};
int main()
{
}
在非类型模板参数声明之前添加额外的typename
关键字是否有效?
请注意,以下代码无法编译(如C++14 (flag -std=C++14
),C++03和C++11代码):
typedef int T;
enum E{};
template <typename T t>
struct ST{};
template <typename E e>
struct SE{};
int main()
{
}
但是下面一个会再次编译好(C++14,C++03和C++11):
typedef int T;
enum E{};
template <typename ::T>
struct ST{};
template <typename ::E>
struct SE{};
int main()
{
}
答案 0 :(得分:6)
允许,但只能使用合格的名称:
typename-specifier:
typename
nested-name-specifier identifier
typename
嵌套 - 名称说明符template
opt 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标准的完全相同的位置。