两阶段查找 - 需要解释

82

编译器在编译模板类时使用两阶段查找意味着什么?


1
@Nawaz 我只听说过两阶段查找,我有什么遗漏的吗? - smallB
2
可以在http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html找到有关该主题的简要而有用的文章。 - Nikola Smiljanić
1
请参考以下链接:https://dev59.com/U2LVa4cB1Zd3GeqPzL2Q#10171507 和 https://dev59.com/uWw05IYBdhLWcg3wiyRJ#7241548。 - Sebastian Mach
1个回答

77

模板至少被编译两次:

  1. 在未实例化时,模板代码本身会被检查语法。
    例如: 任何语法错误如 ; 等。

  2. 在实例化时(当确切的类型已知),模板代码再次被检查以确保所有调用对于该特定类型都是有效的。
    例如: 模板可能反过来调用函数,但这些函数可能不存在于该特定类型中。

这称为两阶段查找


55
请注意,非依赖名称的查找是在第一阶段完成的,而对于依赖于模板参数的名称的查找则是在第二阶段完成的。其意义在于,如果您调用 sqrt(1),则需要在定义模板之前声明 sqrt。但如果您调用 sqrt(t),其中 t 是类型参数的实例,则无需在实例化模板之前看到 sqrt。MSVC 以前无法正确执行此操作:我不知道现在是否还存在这个问题。 - Steve Jessop
14
无论如何,这就是为什么它被称为两阶段“查找”,而不是仅仅两阶段编译之类的东西。第一阶段应该做的不仅仅是检查语法,但是微软在实现第一个查找阶段时遇到了一些困难,所以他们只是在实例化时全部完成了:https://dev59.com/cW015IYBdhLWcg3w_Q4_ - Steve Jessop
@SteveJessop:听起来更像了——两阶段查找的关键在于“查找”部分。谢谢! - Kerrek SB
3
历史背景说明:我曾经使用过一种编译器,它有一个计数花括号的阶段和一个编译阶段,也就是说,如果给定“template <class T> class C { put really anything here & ~ - (but nothing unbalanced and no 8-bit char outside string literal) }”,只要没有实例化“C”,就能通过编译!那是十多年前的事了。 - curiousguy
2
对于好奇的人,这是来自《C++模板:完全指南》的摘录。 - legends2k
3
除了 @SteveJessop 对于“dependent names”的评论之外,还值得指出的是,在“dependent names”上发生的是“argument dependent lookup”。这意味着 ::sqrt(::NS::A) 不会被找到,因为额外的查找将在 ::NS 中进行而不是 :: 中。最后一个要点是,别名、typedef 或 using 的作用域不会被搜索,只有被别名的类型本身的作用域会被搜索。 - Richard Corden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接