[英]ADL bug in VS2012?
我怀疑以下是编译器错误,但我正在寻找验证。 我看过其他与此类似但又不完全匹配的问题。
这是代码:
namespace my {
// using std::swap;
// Convenience utility
template<typename T> void doSwap(T& l, T& r)
{
using namespace std;
swap(l,r);
}
template<typename T> struct Container
{
T t;
void swap(Container<T>& r) { doSwap(this->t,r.t); }
};
// Specialize swap() for Container<T>
template<typename T> void swap(Container<T>& l, Container<T>& r)
{ l.swap(r); }
}
void stuff()
{
my::Container<int> one;
my::Container<int> two;
one.swap(two);
}
当我使用Visual Studio 2012进行编译时,出现以下错误:
error C2784: 'void my::swap(my::Container<T> &,my::Container<T> &)' : could not deduce template argument for 'my::Container<T> &' from 'int'
see reference to function template instantiation 'void my::doSwap<T>(T &,T &)' being compiled
with
[
T=int
]
如果取消注释我的命名空间顶部的using std::swap
,则可以正常工作。 无论哪种方式,相同的代码都可以在clang和g ++下编译,而无需发出警告。
是的,此代码有效。 但是您using namespace std;
应该using std::swap;
。 当前在您的代码中,就好像已在全局范围内声明了std::swap
函数(因为这是同时包含std
和my
的最小包围范围)。对于using namespace
指令,所有声明在该范围内均可见)。 如果您在doSwap
之前移动了另一个swap
重载,那么Clang和GCC也会失败。
template<.....> void swap(....); // from namespace std
namespace my {
// using std::swap;
// Convenience utility
template<typename T> void doSwap(T& l, T& r)
{
using namespace std;
swap(l,r);
}
// ...
在原始代码中,在符合Standards的编译器上,这应该查找一次swap
,并在全局名称空间中找到swap
。 然后,在实例化时应再次查看调用,并注意调用参数为int
,并且int
不可能实现ADL。 在实例化时,不允许再次进行常规查找,而只能再次进行ADL。 因此,结果将仍然是全局swap
并且一切正常。
但是MSVC似乎也在实例化时也在进行正常的调用查找(可能是由于其模板解析模型。MSVC不会在定义模板时解析模板,而仅在使用具体类型实例化时解析)。 也许当时可见swap
命名空间内过载my
干涉,阻止考虑全局查找swap
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.