ADL 和函数模板查找
函数模板在 C 编程中发挥着重要作用,可实现代码重用和通用功能。但是,当使用参数依赖查找 (ADL) 在特定命名空间中查找函数模板时,会出现一个微妙的限制。
尝试使用显式模板参数调用函数模板时,该问题就会显现出来,如以下代码所示snippet:
namespace ns { struct foo {}; template<int i> void frob(foo const&) {} void non_template(foo const&) {} } int main() { ns::foo f; non_template(f); // This is fine. frob<0>(f); // This is not. }
此失败背后的原因源于 C 标准中的特定条款。根据 C 标准 03 14.8.1.6,在使用显式模板参数调用函数模板时,ADL 不适用,除非具有该名称的函数模板在调用时可见。
在上面的示例中,有当 frob(f); 时,当前作用域中没有可见的名为 frob 的函数模板被称为。因此,ADL 不会被触发,编译器无法找到所需的函数模板。
为了规避这一限制,可以在函数模板之前显式指定命名空间,如下所示:
ns::frob<0>(f);
在这种情况下,ADL 不是必需的,因为函数模板是直接从包含的命名空间调用的。
以下代码示例进一步说明了 ADL 与函数的行为templates:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); //ill-formed: not a function call A::f<3>(b); //well-formed C::f<3>(b); //ill-formed; argument dependent lookup // applies only to unqualified names using C::f; f<3>(b); //well-formed because C::f is visible; then // A::f is found by argument dependent lookup }
在这个例子中,函数模板 f 在命名空间 A 和 C 中都被定义。创建完成后,编译器首先检查当前作用域,发现没有可见的 f 模板。然后应用 ADL,但由于 f 是非限定名称,因此它无法在其他命名空间中找到函数模板。
要从命名空间 C 调用模板,必须使用 C::f 或 using 指令显式限定该名称如代码所示。
以上是为什么参数依赖查找 (ADL) 在显式实例化函数模板时失败?的详细内容。更多信息请关注PHP中文网其他相关文章!