不合格的名称查找
这是来自标准(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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在
f&lt; n :: a&gt;(n :: a())
中,&lt;
可以是一个不太算手的操作员,也可以启动模板参数列表。为了消除歧义,编译器需要查看f
(&lt;
之前的名称)是否为模板。请注意,此时无法执行ADL,因为当编译器查看
&lt;
时,他们甚至都不知道是否有参数。C ++ 20指定,如果通常的名称查找找不到,
f
被视为 template-name 。因此,&lt;
被认为是启动模板参数列表,这意味着f&lt; n :: a&gt;
被解析为模板ID,这意味着> code> f&lt; n :: a&gt;(n :: a())
被解析为函数调用表达式,这意味着f
的确是什么。在C ++ 20之前,
&lt;
之前的名称被视为A template-name ,并且仅当通常的名称查找找到模板,因此这些都没有发生,因此代码>&lt; 被视为操作员,f&lt; n :: a&gt;(n :: a())
被视为错误。更改由 p0846r0 。
c ++ 20 /a>:
c ++ 20 /a>:
最新的草稿可以说是更清晰( [temp.names]/3 ):
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 whetherf
(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<
in question is considered to start a template argument list, which meansf<N::A>
is parsed as a template-id, which meansf<N::A>(N::A())
is parsed as a function call expression, which meansf
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, andf<N::A>(N::A())
is treated as an error.The change was made by P0846R0.
C++20 [temp.name]/2:
C++20 [temp.names]/3:
The latest draft arguably makes it clearer ([temp.names]/3):
它称为参数依赖性名称查找[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 namespaceN
, so it [compiler] considers name lookup in that scope too.With function [template]
g()
it is almost the same, except thevoid 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 namespaceh
is a variable, so you can't use it as a function or function template.编译器在当前名称空间中启动查找。然后,如果需要,它继续查看参数的命名空间,以查找可能的功能超载。
在最后一个情况下,
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 asint h
, not a function. So no need to look for function overloads. The compiler then finds that usingh
as a template function doesn't work (as it isint h;
- an error).