【问题标题】:Are both the keyword "typename" and "template" not necessary in this case?在这种情况下,关键字“typename”和“template”是否都不需要?
【发布时间】:2021-08-03 09:11:11
【问题描述】:
template<class T> 
T::type<int> f(){
    
}

根据 [temp.names#3.4]

如果一个

  • [...]
  • 在 using-declarator ([namespace.udecl])、declarator-id ([dcl.meaning]) 或 在除嵌套名称之外的纯类型上下文中的终端名称-说明符 ([temp.res])。

根据 [temp.res#general-4.3.1],T::type&lt;int&gt; 确实满足上述规则(强调我的),因为以下规则

如果一个限定或非限定名称是 type-only 上下文,如果它是

的终端名称
  • [...]
  • a 的 decl-specifier-seq 的 decl-specifier
  • [...]
  • 命名空间范围内的简单声明或函数定义,

T::type&lt;int&gt; 是位于命名空间范围内的模板函数ffunction-definition 的decl 说明符,因此终端名称type 被称为在类型中- 仅限上下文。

另外,根据 [temp.res#general-5]

一个合格的ID,它的终端名称是依赖的并且在一个仅类型的上下文中被认为是一个类型。

因此,T::type&lt;int&gt; 中的符号 &lt; 由于 [temp.names#3.4] 被解释为模板参数列表的分隔符,而限定 ID T::type&lt;int&gt; 被认为表示到期类型到 [temp.res#general-5],这个例子应该是合法的。但是被Clang and GCC都拒绝了。

我想知道,在未来的实现编译的这个示例中,关键字typenametemplate 是否都不需要?

【问题讨论】:

  • 是不是还需要template关键字来表示模板的开始?我认为您只能在内部模板类型中省略它,但我仍然希望保留它,因为它更易于阅读。
  • @Dai 我认为 template 在这种情况下没有必要表明 type 是模板名称,因为 [temp.names#3.4]。
  • 对,但f 是实际的函数模板。
  • @Dai 是的,f 被声明为函数模板,但是,[temp.res#general-4.3.1] 指的是语法,它没有不要说函数定义的 decl 说明符。
  • 我怀疑Where and When Do I Put the template and typename keywords? 至少可以说明其中的一部分。

标签: c++ language-lawyer


【解决方案1】:

是的,这是规则,它正确;编译器还没有实现(更新的)template 部分。在讨论该添加时,提出了一个示例,说明在这种情况下要求关键字是荒谬的:

template<typename T> struct A {
  template<typename U> struct B {
    B();
  }; 
  template<typename U> B<U> make();
};
template<typename T> template<typename U>
A<T>::B<U>::B() {} // no 'template' keyword required before 'B' here, but...
template<typename T> template<typename U>
A<T>::B<U> A<T>::make() { return {}; } // 'template' keyword required before 'B' here?

这也说明了在许多情况下放弃typename 要求的部分动机。 A&lt;T&gt;::B 可能 是一个从属名称(如果声明最终用于不是A 的(主要模板)成员的东西),但这不会干扰解析它,因为那里不能出现表达式

【讨论】:

  • A&lt;T&gt;::B&lt;U&gt;::B() 中不需要关键字template,因为declarator-id [temp.names#3.4]; templateA&lt;T&gt;::B&lt;U&gt; A&lt;T&gt;::make() 中不需要关键字A&lt;T&gt;::B&lt;U&gt; A&lt;T&gt;::make() 与此问题中的示例类似(即由于[temp.res#general-4.3.1]),对吧?
  • @xmh0511: 是的,make 的情况类似,但它们都应该通过 type-only 规则,因为构造函数声明中的第一个 B 不是终端declarator-id 的名称。该规则需要调整以包含 nested-name-specifier,它们本身就在纯类型上下文中。
  • 啊,我刚刚发现A&lt;T&gt;::B&lt;U&gt;::B中的第一个B不是declarator-id的终端名,我上面的注释错了,好像没有当前草案中的规则解释了为什么在这种情况下可以省略template(即,应该修复以涵盖这种情况)。
  • 这里的另一个混淆是 [temp.names#3.4] 关于 using-declarator,根据 [namespace.udecl#5],using Test::tmp_id&lt;T&gt; 应该是错误的。我不知道这里的意图。该规则是否只是使“
  • @xmh0511:它仍然被解释为模板参数列表:它只是一个不允许的模板参数列表。真正的目的当然是typename
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
相关资源
最近更新 更多