本文介绍了无法理解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查找和非限定ID查找

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


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

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

因此,使用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相关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 12:50