为什么仍然需要在使用语句的RHS中用typename来消歧一个依赖types?
我很清楚为什么需要为依赖types使用typename
,因为编译器可能无法在types和variables声明之间消除歧义,当它看到像T::type
这样的东西时,请参阅这个答案,以获得很好的解释。 TL; DR :在像T::type * x;
这样的expression式中T::type * x;
,编译器不能“知道” T::type
是一个types,还是T
一些特定的专门化中声明的variables。
然而,在类似的东西
using type = T::type;
没有什么暧昧的。 IMO, T::type
应该总是被parsing为一个types ,因为它是using
语句的RHS的一部分。 但是,我们仍然需要在这里使用typename
(至less根据gcc和clang)
using type = typename T::type;
住在Coliru,gcc 住在Coliru,铛
Visual C ++ 似乎接受没有types名称的代码 ,但我没有太多的信心,编译器完全符合标准(事实上,它有许多非标准的扩展,例如绑定右值到非const引用)。
问题 :为什么这不是C ++ 11及更高版本中的typename
规则的例外?
没有困难的原因。 正如ralismark所说 ,今年讨论了一篇论文(C ++ 20,而不是17)。 有担忧,也有对立面:
- 它可以被看作是使语言不那么规律(正如codeshot所说的 ),但是新的想法是,消除歧义的
typename
会变得非常稀缺,从而在另一个方向上具有接近一致性。 (正如前面所说的 ,已经有一个以基类名称的forms出现的例外情况) - 它可能会阻止可能的扩展(如TC报告 ),但扩展可能有自己的消歧,而不是负担常见的情况。
这份文件得到了有力的支持,新的规定很可能会在几个月内出现在工作草案中。
模板参数typesT不会,并且不能隐式地携带它的内部组件。 因此,当编译器查看未被实例化的模板时,T :: type基本上是一个新types,因此需要声明一个新的types名'T :: type'。
不幸的是,我认为这个问题将一直存在,直到标准包含完整的概念。