无法理解int和用户定义类型之间的名称查找差异-可能与ADL相关 [英] Can't understand name lookup differences between an int and a user defined type - perhaps ADL related

查看:110
本文介绍了无法理解int和用户定义类型之间的名称查找差异-可能与ADL相关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么以下代码会编译:

Why does the following code compile:

template<typename T>
void foo(T in) { bar(in); }

struct type{};
void bar(type) {}
int main() { foo(type()); }

以下情况除外:

template<typename T>
void foo(T in) { bar(in); }

void bar(int) {}
int main() { foo(42); }

使用GnuC ++ 7进行编译:

Compiling with GnuC++ 7:

a.cpp: In instantiation of 'void foo(T) [with T = int]':
a.cpp:9:20:   required from here
a.cpp:2:21: error: 'bar' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
 void foo(T in) { bar(in); }
                  ~~~^~~~
a.cpp:8:6: note: 'void bar(int)' declared here, later in the translation unit void bar(int) {}

我认为MSVC会编译两者(确实如此),但GCC会拒绝两者,因为GCC/Clang具有正确的两阶段名称查找...

I would assume that MSVC would compile both (as it does) but that GCC would reject both since GCC/Clang have proper two phase name lookup...

推荐答案

奇怪的部分不是int示例无法编译,而是type示例执行了,因为bar是在.这是由于[temp.dep.candidate](请参阅第三段).

The strange part is not that the int example fails to compile, it is that the type example does since bar is defined after foo. This is due to [temp.dep.candidate] (see third paragraph).

当编译器解析并编译模板类或函数时,它将通过两遍查找标识符:

When the compiler parses and compiles a template class or function, it looks up identifiers in two pass:

  • 模板参数独立名称查找:可以检查所有不依赖模板参数的内容.在这里,由于bar()取决于模板参数,因此什么也没做.查找是在定义时完成的.
  • 依赖模板参数的名称查找:现在可以通过通行证#1查找所有内容.查找是在实例化时完成的.
  • Template argument independent name lookup: everything that does not depend on the template arguments can be checked. Here, since bar() depends on a template argument, nothing is done. This lookup is done at the point of definition.
  • Template argument dependent name lookup: everything that could not be looked up in pass #1 is now possible. This lookup is done at the point of instantiation.

在通行证2中出现错误.

You get an error during pass #2.

查找函数名称时,它是在当前上下文和参数类型的上下文中完成的.例如,尽管在名称空间n中定义了f,以下代码仍然有效:

When a function name is looked up, it is done within the current context and those of the parameters type. For instance, the following code is valid though f is defined in namespace n:

namespace n { struct type {}; void f(type) {}; }
int main() { n::type t; f(t); } // f is found in ::n because type of t is in ::n

有关ADL的更多信息(cppreference.com):

依赖于参数的查找(也称为ADL或Koenig查找)是用于在函数调用表达式中查找不合格函数名称的规则集,包括对重载运算符的隐式函数调用.除了通常的非限定名称查找所考虑的范围和名称空间之外,还在其参数的名称空间中查找这些函数名称.

Argument-dependent lookup, also known as ADL, or Koenig lookup, is the set of rules for looking up the unqualified function names in function-call expressions, including implicit function calls to overloaded operators. These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.


两遍编译,ADL查找和非限定ID查找

在您的情况下,这三种机制相互冲突.参见[临时候选人]:


Two-pass compilation, ADL lookup and unqualified-id lookup

In your case, those three mechanisms collide. See [temp.dep.candidate]:

对于依赖于模板参数的函数调用,如果函数名称是非限定ID但不是模板ID,则 使用通常的查找规则找到候选函数(3.4.1, 3.4.2),除了:
—对于使用非限定名称查找(3.4.1)的查找,只有从外部连接使用外部链接的函数声明 找到模板定义上下文.
—对于使用关联的名称空间(3.4.2)进行的查找,只有在具有以下功能的函数声明中才能找到 模板定义上下文或模板实例化上下文是 找到了.

For a function call that depends on a template parameter, if the function name is an unqualified-id but not a template-id, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2) except that:
— For the part of the lookup using unqualified name lookup (3.4.1), only function declarations with external linkage from the template definition context are found.
— For the part of the lookup using associated namespaces (3.4.2), only function declarations with external linkage found in either the template definition context or the template instantiation context are found.

因此,使用foo(type())进行非限定ID查找并在在模板定义上下文或模板实例化中"完成查找..
foo(42)42为基本类型,不考虑ADL,而仅考虑定义上下文" .

So, with foo(type()) unqualified-id lookup kicks in and the lookup is done "in either the template definition context or the template instantiation".
With foo(42), 42 being a fundamental type, ADL is not considered and only the "definition context" is considered.

这篇关于无法理解int和用户定义类型之间的名称查找差异-可能与ADL相关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆