struct A{};
template <typename T>
struct B
{
typename ::A a1; //(1)
typename A a2; //(2): error
};
int main(){return 0;}
为什么第一种情况正确,但第二种情况不正确?我不明白这种限制的含义
无论如何,为什么第一个案例被允许? ::A
不依赖于模板参数的名称。它的含义是什么?
答案 0 :(得分:6)
规则并不是如果类型嵌套在依赖范围内,则只能使用typename
。规则或多或少:
typename
typename
。语法允许它为 qualified-id 的子集,由
指定typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template<opt> simple-template-id
nested-name-specifier:
:: (C++14 or later)
::<opt> type-name ::
::<opt> namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier template<opt> simple-template-id ::
所以第二种情况肯定是禁止的,因为它不涉及任何嵌套。严格地说,在C ++ 14之前,第一个也被禁止,因为全局限定符::
与该语法不匹配。
答案 1 :(得分:5)
正如@MikeSeymour's answer解释的那样,严格遵循标准(C ++ 11,我手边没有C ++ 14文本),案例(1)实际上也应该是错误的 - 只有在typename
左侧至少有一个名称时,才能使用::
作为限定名称的前缀。
但是,正如@hvd在评论中指出的那样,CWG issue 382表示实际意图是在任何限定名称之前允许typename
,包括全局命名空间限定。由于这是大多数编译器似乎实现的,所以本答案的其余部分都遵循这个想法。
当这样看时,并非如果情况(2)是限制,那么情况(1)就是仁慈。所需的规则(以及我非常原始的措辞,我相信)基本上是&#34;如果依赖于模板参数的限定名称表示类型,则必须在其前面添加typename
。&#34;为方便起见,它被放宽为&#34; typename
可以用于任何类型的合格名称,无论它是否依赖。&#34; (1)
相比之下,非限定名称永远不会含糊不清,无论它是否引用某种类型,因此永远不需要typename
,因此不允许typename
。
(1)这种放松并没有在标准中明确说明,而是来自几个规则的组合。基本上,只要允许简单类型说明符(表示类型的东西),语法也允许 typename-specifier (前缀为{{1的限定名称) }})。模板规则(主要在14.6中)仅表示当从属限定名称表示类型时需要typename
。由于在其他上下文中没有禁止typename
,因此它可以与任何表示类型的限定名称一起使用(甚至在模板上下文之外)。