考虑以下代码:
#include <iostream>
namespace A {
struct Mine {};
template <typename T1, typename T2>
void foo(T1, T2)
{
std::cout << "A::foo" << std::endl;
}
}
namespace B {
template <typename T>
void foo(T, T)
{
std::cout << "B::foo" << std::endl;
}
}
using namespace A;
using namespace B;
// or with the same effect:
//using A::foo;
//using B::foo;
int main()
{
A::Mine a;
foo(a, a);
}
该程序将打印B::foo
而不是A::foo
。为什么使用B::foo
而不是A::foo
?想象一下以下情况:您的库提供了一个 namespace
A
,而其他一些库提供了 namespace B
,其中包括一个功能模板,该功能模板的名称与您的库相同。通常,没有问题,因为可以使用限定调用或依赖于参数的查找来选择正确的版本。但是,如果用户使用foo
声明将A::foo
和B::foo
引入相同的作用域,则不合格的调用不会产生歧义,但可能会选择错误的函数。有一种方法可以选择
using
而不是A::foo
,因为应该根据依赖于参数的查询选择B::foo
?在这种情况下,您有什么建议? 最佳答案
它实际上是在做正确的事情。这就是原因。
namespace A {
struct Mine {};
template <typename T1, typename T2>
void foo(T1, T2)
{
std::cout << "A::foo" << std::endl;
}
}
当有2个不同(或相同)类型的参数传递时,上述代码将匹配。因为您对T1
和T2
的定义不同(但它们也可以相同)。但是函数调用是foo(a, a);
具有相同类型的两个参数。现在,在
foo
中定义了具有2个相同类型参数的namespace B
方法,如下所示namespace B {
template <typename T>
void foo(T, T)
{
std::cout << "B::foo" << std::endl;
}
}
因此namespace B
中的方法是匹配的,因为两个签名都不同。尝试添加以下代码
namespace C {
template <typename T>
void foo(T, T)
{
std::cout << "B::foo" << std::endl;
}
}
并最终导致编译器错误,在方法定义中指定歧义,然后您必须使用A::foo(a,a)
之类的东西或希望使用的任何命名空间来手动解析foo的范围。