不合格的名称查找

发布于 2025-02-02 11:41:54 字数 621 浏览 1 评论 0原文

这是来自标准(C ++ 20) - 不合格的名称查找6.5.2。 有人可以解释一下这里发生的事情吗?注意:这不是ADL。我特别正在寻找对此简短句子的阐明:“在某些情况下,<的名称也被视为 template-name ,即使名称查找未找到 template-name

int h;
void g();
namespace N{
  struct A{};
  template <class T> int f(T);
  template <class T> int g(T);
  template <class T> int h(T);
}
int x = f<N::A>(N::A()); // OK: lookup of f finds nothing; f treated as template name
int y = g<N::A>(N::A()); // OK: lookup of g finds a function, g treated as template name
int z = h<N::A>(N::A()); // error: h< does not begin a template-id

This is from the standard (C++20) - unqualified name lookup 6.5.2.
Can anyone please explain what's going on here ? Note: this is not ADL. I am specifically looking for an elucidation of this brief sentence: "In some cases a name followed by < is treated as a template-name even though name lookup did not find a template-name"

int h;
void g();
namespace N{
  struct A{};
  template <class T> int f(T);
  template <class T> int g(T);
  template <class T> int h(T);
}
int x = f<N::A>(N::A()); // OK: lookup of f finds nothing; f treated as template name
int y = g<N::A>(N::A()); // OK: lookup of g finds a function, g treated as template name
int z = h<N::A>(N::A()); // error: h< does not begin a template-id

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼眸里的那抹悲凉 2025-02-09 11:41:55

f&lt; n :: a&gt;(n :: a())中,&lt;可以是一个不太算手的操作员,也可以启动模板参数列表。为了消除歧义,编译器需要查看f&lt;之前的名称)是否为模板。

请注意,此时无法执行ADL,因为当编译器查看&lt;时,他们甚至都不知道是否有参数。

C ++ 20指定,如果通常的名称查找找不到,f被视为 template-name 。因此,

  1. &lt;被认为是启动模板参数列表,这意味着
  2. f&lt; n :: a&gt;被解析为模板ID,这意味着
  3. > code> f&lt; n :: a&gt;(n :: a())被解析为函数调用表达式,这意味着
  4. 执行ADL以查看f的确是什么。

在C ++ 20之前,&lt;之前的名称被视为A template-name ,并且仅当通常的名称查找找到模板,因此这些都没有发生,因此代码>&lt; 被视为操作员,f&lt; n :: a&gt;(n :: a())被视为错误。

更改由 p0846r0

c ++ 20 /a>:

AN 标识符是A template-name ,如果它通过名称查找与模板或包含功能模板的过载集相关联,或者是标识符之后是&lt; template-id 将形成一个 nofqualified-id ,名称查找要么找到一个或多个功能或什么都没找到。


c ++ 20 /a>:

当名称被视为 template-name ,然后是&lt;&lt;始终是作为 template-argument-list 的定界符,从不作为运算符。

最新的草稿可以说是更清晰( [temp.names]/3 ):

a &lt;被解释为 template-argument-list 的定界符,如果它遵循的名称不是转换>函数-ID < /em>和

  • [...]
  • 这是一个不合格的名称,该名称查找可以找到一个或多个函数或什么也没有找到,或者
  • [...]。

In f<N::A>(N::A()), the < can either be a less-than operator or start a template argument list. To disambiguate, compilers need to see whether f (the name before <) names a template.

Note that it's impossible to perform ADL at this point, because when compilers see <, they do not even know whether there are arguments.

C++20 specifies that if usual name lookup finds nothing, f is treated as a template-name. Thus

  1. < in question is considered to start a template argument list, which means
  2. f<N::A> is parsed as a template-id, which means
  3. f<N::A>(N::A()) is parsed as a function call expression, which means
  4. ADL is performed to see what f really is.

Before C++20, the name before < is treated as a template-name if and only if usual name lookup finds a template, so none of these happen, < is considered as an operator, and f<N::A>(N::A()) is treated as an error.

The change was made by P0846R0.

C++20 [temp.name]/2:

An identifier is a template-name if it is associated by name lookup with a template or an overload set that contains a function template, or the identifier is followed by <, the template-id would form an unqualified-id, and name lookup either finds one or more functions or finds nothing.

C++20 [temp.names]/3:

When a name is considered to be a template-name, and it is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator.

The latest draft arguably makes it clearer ([temp.names]/3):

A < is interpreted as the delimiter of a template-argument-list if it follows a name that is not a conversion-function-id and

  • [...]
  • that is an unqualified name for which name lookup either finds one or more functions or finds nothing, or
  • [...].
瞳孔里扚悲伤 2025-02-09 11:41:55

它称为参数依赖性名称查找[6.5.2],当使用不合格的名称查找时的特殊规则。

调用函数[或函数模板,规则相同]时,ADL使编译器考虑其参数的名称空间。

对于函数[模板] f()编译器所看到的,您在命名空间n中提供了参数,因此[编译器]也考虑了该范围中的名称查找。

使用函数[template] g()几乎是相同的,除了void g();声明是在过载分辨率下考虑的,因为::::::::: g() [顶级名称空间]没有任何参数,n :: g() wins。

使用h()它是不同的。可变名称​​不能超载。对于顶级名称空间H是一个变量,因此您不能将其用作函数或功能模板。

It is something called argument-dependent name lookup [6.5.2], the special rules when unqualified name lookup is used.

When calling a function [or function template, rules are the same], ADL makes the compiler consider the namespace of its arguments.

For function [template] f() compiler sees, that you provided argument in the namespace N, so it [compiler] considers name lookup in that scope too.

With function [template] g() it is almost the same, except the void g(); declaration is considered at the overload resolution, since the ::g() [top-level namespace] does not have any arguments, N::g() wins.

With h() it is different. Variable names cannot be overloaded. For the top-level namespace h is a variable, so you can't use it as a function or function template.

殊姿 2025-02-09 11:41:55

编译器在当前名称空间中启动查找。然后,如果需要,它继续查看参数的命名空间,以查找可能的功能超载。

在最后一个情况下,h被发现为int h,而不是函数。因此,无需寻找功能过载。然后,编译器发现使用h作为模板函数不起作用(因为它是int H; - 错误)。

The compiler starts the lookup in the current namespace. It then, if needed, goes on to look in the namespace(s) of parameters to find possible function overloads.

In the last case h is found as int h, not a function. So no need to look for function overloads. The compiler then finds that using h as a template function doesn't work (as it is int h; - an error).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文