【问题标题】:type-dependent nested-name-specifier in elaborated-type-specifier详细类型说明符中的类型相关嵌套名称说明符
【发布时间】:2014-02-22 09:57:55
【问题描述】:

this question 之前,我从未在详细类型说明符中看到嵌套名称说明符,乍一看我认为它甚至没有被语法覆盖。现在我看到,从 C++98 到现在,它被翻译为没有 typename-specifier 构造的特殊情况。 C++11 7.1.6.3/2(C++98 中为 7.1.5.3/2):

3.4.4 描述了如何在 elaborated-type-specifier 中为 identifier 进行名称查找。如果 identifier 解析为 class-nameenum-name,则 elaborated-type-specifier 会引入它以 simple-type-specifier 引入其 type-name 的相同方式进入声明。

因此,尽管您可以形成一个合格的详细类型说明符,但您需要注意它永远不会依赖于类型。 3.4.4 在模板定义时的名称解析永远不会找到类名,因为依赖名称被假定为对象,除非以 typename 关键字为前缀,这在此上下文中的语法上是不允许的。

这是对标准含义和语言设计意图的准确评估吗?

【问题讨论】:

  • 我不明白为什么它是依赖于类型的,只要查找发生在实例化点。这就是 clang 实现的,这就是为什么它允许 struct S1<T>::I 却将 struct S2<T>::I 诊断为 ideone.com/paV3Kh 中的错误(注意:ideone 使用 GCC,而 GCC 允许这样做,所以你看不到那里的错误)跨度>
  • @hvd 有趣又奇怪;谢谢!但我真正想知道的是为什么不需要typename 关键字。实际上我还没有查找不需要的异常列表,所以我现在就去做……
  • 好点。引用 14.6p2:“在模板声明或定义中使用且依赖于 template-parameter 的名称被假定为不命名类型,除非适用的名称查找找到类型名称或名称是由关键字typename 限定。”我也没有看到允许struct S1<T>::I 的异常。
  • 啊! 14.6p5:“在 mem-initializer-idbase-specifierelaborated-type-specifier 中用作名称的限定名称i> 被隐式假定为命名一个类型,而不使用 typename 关键字。在立即包含 nested-name-specifiernested-name-specifier 中取决于模板参数,identifiersimple-template-id 被隐式假定为命名类型,而不使用 typename 关键字。"跨度>

标签: c++ templates


【解决方案1】:

从 cmets 扩展:

以这个程序为例:

template <typename T>
struct S1 { struct I { }; };

template <typename T>
struct S2 { typedef struct S1<T>::I I; }; // okay

template <typename T>
struct S3 { typedef struct S2<T>::I I; }; // okay at definition time
                                          // usually error at instantiation time
template <>
struct S2<short> : S1<short> { };

int main() {
  S1<int>::I a;
  S2<int>::I &b = a; // okay
  S3<int>::I &c = b; // error
  S1<short>::I d;
  S2<short>::I &e = d; // okay
  S3<short>::I &f = e; // okay
}

在模板定义时,S2S3 都可以:14.6p5 列出了不需要typename 的例外情况。本质上:如果使用是明确的,因为名称只能是类型,typename 不是必需的。这包括在语法上不允许typename 的几种情况,因此需要typename 意味着无法编写程序。 typename struct S&lt;T&gt;::Istruct typename S&lt;T&gt;::I 都是硬错误,struct S&lt;T&gt;::I 是明确的。

在模板实例化时,3.4.4 的规则更加清晰:struct S1&lt;int&gt;::Istruct S2&lt;int&gt;::I 都可以找到,其中很明显 S2&lt;int&gt;::I 是一个 typedef,所以 struct S2&lt;int&gt;::I 是一个错误。同时,此时S2&lt;short&gt;::I 被视为不是typedef,而是结构,因此struct S2&lt;short&gt;::I 是允许的。

【讨论】:

  • 谢谢!带来不便敬请谅解;这个问题只是我记忆错误的结果,我会在不久前发布一个答案,但我的互联网连接中断了:P
  • @Potatoswatter 我不知道这个,所以就我自己的 C++ 知识而言,你问得很好。 :)
猜你喜欢
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
相关资源
最近更新 更多