无法理解 int 和用户定义类型之间的名称查找差异 - 可能与 ADL 相关

2024-06-26

为什么下面的代码可以编译通过:

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 编译:

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 有适当的两阶段名称查找...


奇怪的部分并不是int示例无法编译,这是type例子是因为bar是在之后定义的foo。这是由于 [temp.dep.candidate] (参见第三段)。

模板的两遍编译

当编译器解析和编译模板类或函数时,它会分两遍查找标识符:

  • 模板参数独立名称查找:可以检查不依赖于模板参数的所有内容。在这里,自从bar()取决于模板参数,什么也不做。该查找是在定义点完成的。
  • 模板参数相关名称查找:在第 1 遍中无法查找到的所有内容现在都可以实现。该查找是在实例化时完成的。

您在第 2 遍过程中遇到错误。


ADL 查找

当查找函数名称时,它是在当前上下文和参数类型的上下文中完成的。例如,下面的代码是有效的f定义在命名空间中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) http://en.cppreference.com/w/cpp/language/adl:

参数相关查找,也称为 ADL 或 Koenig 查找,是一组用于在函数调用表达式中查找非限定函数名称的规则,包括对重载运算符的隐式函数调用。除了通常的非限定名称查找所考虑的范围和名称空间之外,还会在其参数的名称空间中查找这些函数名称。


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

就您而言,这三种机制发生了冲突。请参阅[temp.dep.candidate]:

对于依赖于模板参数的函数调用,如果函数名称是 unqualified-id 但不是 template-id,则 使用通常的查找规则(3.4.1, 3.4.2) 除了:
— 对于使用非限定名称查找(3.4.1)的查找部分,仅具有来自 找到模板定义上下文。
— 对于使用关联命名空间 (3.4.2) 的查找部分,仅在以下任意一个中找到具有外部链接的函数声明: 模板定义上下文或模板实例化上下文是 成立。

所以,与foo(type())启动不合格 ID 查找并完成查找“在模板定义上下文或模板实例化中”.
With foo(42), 42作为基本类型,不考虑 ADL,仅考虑“定义上下文”被认为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法理解 int 和用户定义类型之间的名称查找差异 - 可能与 ADL 相关 的相关文章

  • 使用可加载内核模块修改帧缓冲区(/dev/graphics/fb0)参数

    Problem 我必须配置 Android 平台使用的各种 LCD 显示器 几乎在所有情况下 都没有针对感兴趣的 LCD 显示器免费提供的电气规格 但通过经验和逆向工程 可以很好地猜测参数 我正在尝试使用可加载内核模块来微调显示参数 也欢迎
  • 如何使用 LINQ ForEach 更改 List

    我有一个List
  • HTML 文档

    有没有一个工具可以从 VS2010 生成的 XML 文档文件生成 HTML 页面 我在谷歌上搜索了这样的工具 但没有找到 我下载并安装了SandCastle 但我不明白如何使用它 尝试使用Sandcastle 帮助文件生成器 http sh
  • 带方括号的 Uri.EscapeUriString

    这是一个奇怪的问题 但让我们看看它会得到什么样的回应 如果我编写一个控制台应用程序 VS 2013 NET 4 5 1 并执行这行代码 Uri EscapeUriString 我明白了 但是 如果我执行同样的事情 嗯 从技术上来说Uri E
  • 使用索引避免迭代器失效,维护干净的接口

    我创建了一个MemoryManager
  • 在宏中使用 # [重复]

    这个问题在这里已经有答案了 请解释一下代码 include
  • C# Visual Studio 动态代码片段

    我正在开发一个 WinForms 项目 每天都会执行一些重复性的任务 所以我认为创建代码片段 https msdn microsoft com en us library ms165394 v vs 110 aspx会帮助我 但它仅适用于固
  • 如何处理作为参数传递到方法中的 Lambda 表达式 - C# .NET 3.5

    我对 Lambda 表达式的了解有点不稳定 虽然我可以编写使用 Lambda 表达式 又名 LINQ 的代码 但我正在尝试编写自己的方法 该方法采用一些 Lambda 表达式类型的参数 背景 我正在尝试编写一个方法 该方法从任何其他对象类型
  • 在 Windows 服务中使用 OleDb 从 Excel 读取数据?

    免责声明 我知道这是一种不好的做事方式 这是我们与客户的唯一选择 Problem 我们需要每隔 x 时间从 Excel 文件读取数据 数据通过第三方 Excel 插件不断变化 应用程序的环境是 Windows XP SP1 和 Net 2
  • 在 C/C++ 中绘制填充椭圆的简单算法

    在SO上 找到了以下绘制实心圆的简单算法 for int y radius y lt radius y for int x radius x lt radius x if x x y y lt radius radius setpixel
  • 如果 .txt 文件不存在,则创建一个,如果存在则追加新行

    我想创建一个 txt 文件并写入它 如果该文件已经存在 我只想添加更多行 string path E AppServ Example txt if File Exists path File Create path TextWriter t
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • ASP.NET 中的 thread.sleep

    我正在为我的网站模拟彗星实时馈送协议 因此在我的控制器中我添加 while nothing new before timeout Thread Sleep 1000 但我注意到添加此功能后整个网站变慢了 调试后我得出结论 当我打电话时Thr
  • 第三方引用的 dll 未被复制来构建

    我有一个第三方 net dll 被我的 dll 类库项目 A 引用和使用 我的控制台应用程序项目 B 引用项目 A 我的问题是第三方 dll 没有被复制到控制台应用程序项目 B 的构建中 这里有什么问题呢 我的 dll 类库中引用的第三方
  • 如何在Windows Azure上调用ffmpeg.exe转换音频文件?

    我在 Windows Azure 上运行 Web 角色来接收 AAC 音频文件 通过 base64 字符串上传 并将它们存储到 blob 中 现在效果很好 接下来 我还必须将它们转换为 MP3 并将 MP3 存储到 blob 中 我决定使用
  • 如何在 Windows 8.1 上打开多个 Visual Studio 窗口? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我使用的是 Windows 7 我能够启动多个 Visual Studio 并同时工作 现在我有 Windows 8 1 操作系统 每当我
  • Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

    我有以下 Subsonic 3 0 查询 其中包含嵌套的 NotIn 查询 public List
  • 合并大文件的最佳方法是什么?

    我必须合并数千个大文件 每个大约 200MB 我想知道合并这些文件的最佳方法是什么 行将有条件地复制到合并文件中 可以使用 File AppendAllLines 或使用 Stream CopyTo 吗 使用 File AppendAllL
  • 具有可导出私钥的证书的“错误密钥”例外

    我正在尝试使用非对称加密来加密然后解密文件 我已经使用 makecert 创建了一个测试证书并将其安装到我的个人本地计算机存储中 将来我必须在多个服务器上安装此证书 这就是为什么我使用 pe 标志创建它 即使用可导出的私钥 证书已成功创建并
  • 有关 Endian 性和 .Net 的详细信息?

    我有几个关于字节顺序的问题 这些问题足够相关 我保证将它们作为一个问题提出 1 字节顺序是由 Net还是由硬件决定的 2 如果是由硬件决定的 我怎样才能在C 中找出硬件的字节序 3 字节序是否影响二进制交互 例如 OR AND OR 或移位

随机推荐