本文介绍了为什么两相查找无法选择重载版本的“swap”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我正在学习这个迷人的答案到关于为用户定义的类型实施 c> (而不是 中重载 c> (而不是重载)中的 但是,答案仍然是额外的情况:专业化交换对于用户定义的模板类 - 在这种情况下,无法实现所需的结果。 回答简单的状态它不解释为什么。 有人可以详细说明该答案,并描述查询过程中提供的两个具体代码段该答案: 重载 > 调用 swap()该示例需要一个依赖的名称,因为它的参数 begin [0] 和 begin [1] 取决于模板参数函数模板的code> T 这种依赖名称的两阶段名称查找在标准中定义如下: 14.6.4.2候选函数[temp.dep.candidate] 无限定查找由定义 3.4.1不合格名称查找[basic.lookup.unqual] 和参数相关的查找(ADL)as 3.4.2参数依赖的名称查找[basic.lookup.argdep] 1当函数调用(5.2.2)中的postfix-expression是 unqualified-id 时,在通常情况下不考虑的其他命名空间$ b $可以搜索b未限定查找(3.4.1),并且在这些命名空间中,可以找到不可见的命名空间范围的朋友函数或函数模板声明(11.3)。对搜索的这些修改取决于参数的类型(以及模板模板参数,模板参数的命名空间)。 将标准应用于示例 第一个示例调用 exp :: swap()。这不是从属名称,不需要两阶段名称查找。因为对swap的调用是合格的,所以发生普通查找,其仅找到通用的交换(T&)功能模板。 第二个示例(@HowardHinnant称之为现代解决方案)调用 swap()并且在与类A 相同的命名空间中具有重载交换(A&生命(在这种情况下的全局命名空间)。因为对交换的调用是不合格的,所以普通的查找和ADL在定义点发生(再次只找到通用的交换(T&)), ADL发生在实例化的地方(即 exp :: algorithm()正在 main() ),并且选择交换(A& A,A&),这是在重载解析期间更好的匹配。 到目前为止很好。现在对于encore:第三个示例调用 swap(),并具有模板<在命名空间exp 内部交换(A& A,A&)。查找与第二个示例相同,但现在ADL不会选择模板专用化,因为它不在类A 的关联命名空间中。然而,即使专业化 template<>交换(A& A,A&)在重载解析过程中不起作用,它仍然在使用时被实例化。 ,第四个示例调用 swap(),并具有重载模板< class T&模板< class T>中的命名空间exp 之间交换(A & ; A类居住在全局命名空间中。查找与第三示例中的相同,并且再次ADL不拾取重载交换(A &),因为它不在类模板 A 的关联命名空间中。在这种情况下,还没有必须在使用点处实例化的特殊化,因此在此处调用通用交换(T&),T&)。 结论 即使您不允许向 ,并且只有明确的专业化,它甚至不会工作,因为两个阶段名称查找的各种错综复杂。 I am studying this fascinating answer to a subtle question regarding the best practice to implement the swap function for user-defined types. (My question was initially motivated by a discussion of the illegality of adding types to namespace std.)I will not re-print the code snippet from the above-linked answer here.Instead, I would like to understand the answer.The answer I've linked above states, beneath the first code snippet, in regards to overloading swap in namespace std (rather than specializing it in that namespace):The answer then goes on to point out that specializing swap in namespace std (as opposed to overloading it) produces a different result (the desired result in the case of specialization).However, the answer proceeds with an additional case: specializing swap for a user-defined template class - in which case, again, the desired result is not achieved.Unfortunately, the answer simply states the facts; it does not explain why.Can someone please elaborate on that answer, and describe the process of lookup in the two specific code snippets provided in that answer:overloading swap in namespace std for a user-defined non-template class (as in the first code snippet of the linked answer)specializing swap in namespace std for a user-defined template class (as in the final code snippet of the linked answer)In both cases, the generic std::swap is called, rather than the user-defined swap. Why?(This will shed light on the nature of two-phase lookup, and the reason for the best practice for implementing user-defined swap; thanks.) 解决方案 Preamble with plenty of StandardeseThe call to swap() in the example entails a dependent name because its arguments begin[0] and begin[1] depend on the template parameter T of the surrounding algorithm() function template. Two-phase name lookup for such dependent names is defined in the Standard as follows:14.6.4.2 Candidate functions [temp.dep.candidate]Unqualified lookup is defined by3.4.1 Unqualified name lookup [basic.lookup.unqual]and argument-dependent lookup (ADL) as3.4.2 Argument-dependent name lookup [basic.lookup.argdep]Applying the Standard to the exampleThe first example calls exp::swap(). This is not a dependent name and does not require two-phase name lookup. Because the call to swap is qualified, ordinary lookup takes place which finds only the generic swap(T&, T&) function template. The second example (what @HowardHinnant calls "the modern solution") calls swap() and also has an overload swap(A&, A&) in the same namespace as where class A lives (the global namespace in this case). Because the call to swap is unqualified, both ordinary lookup and ADL take place at the point of definition (again only finding the generic swap(T&, T&)) but another ADL takes place at the point of instantiation (i.e where exp::algorithm() is being called in main()) and this picks up swap(A&, A&) which is a better match during overload resolution. So far so good. Now for the encore: the third example calls swap() and has a specialization template<> swap(A&, A&) inside namespace exp. The lookup is the same as in the second example, but now ADL does not pick up the template specialization because it is not in an associated namespace of class A. However, even though the specialization template<> swap(A&, A&) does not play a role during overload resolution, it is still instantiated at the point of use.Finally, the fourth example calls swap() and has an overload template<class T> swap(A<T>&, A<T>&) inside namespace exp for template<class T> class A living in the global namespace. The lookup is the same as in the third example, and again ADL does not pick up the overload swap(A<T>&, A<T>&) because it is not in an associated namespace of the class template A<T>. And in this case, there is also no specialization that has to be instantiated at the point of use, so the generic swap(T&, T&) is being callled here.ConclusionEven though you are not allowed to add new overloads to namespace std, and only explicit specializations, it would not even work because of the various intricacies of two-phase name lookup. 这篇关于为什么两相查找无法选择重载版本的“swap”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-28 08:13