C++ Visual Studio 2013中可能存在的ADL错误
以下简化代码无法在VS2013下编译:C++ Visual Studio 2013中可能存在的ADL错误,c++,gcc,visual-studio-2013,argument-dependent-lookup,C++,Gcc,Visual Studio 2013,Argument Dependent Lookup,以下简化代码无法在VS2013下编译: #include <cmath> namespace mine { template <typename A> struct Base { double value() const { return static_cast<const A&>(*this).value(); } }; struct Derived : Base < Derived &
#include <cmath>
namespace mine
{
template <typename A>
struct Base
{
double value() const { return static_cast<const A&>(*this).value(); }
};
struct Derived : Base < Derived >
{
Derived(double x) : m_val(x) {}
double value() const { return m_val; }
double m_val;
};
template <typename A>
bool isnan(const Base<A>& x) { return ::isnan(x.value()); }
struct ItWorks
{
double value() const { return 3.14; }
};
bool isnan(ItWorks t) { return ::isnan(t.value()); }
}
int main()
{
mine::Derived d(2.0);
bool b = isnan(d); // this one fails in VS2013
mine::ItWorks t;
bool bb = isnan(t); // this one works
return 0;
}
我原以为ADL在mine::Derived
上调用时会调用mine::isnan()
,但出于某种原因,VS2013正在尝试从全局命名空间调用isnan()
模板函数
当然,如果我直接调用mine::isnan()
,一切都正常工作,但这并不能解决我的问题,因为我需要在一个模板化上下文中调用isnan()
,在这个上下文中,我可能会得到一个double
或从mine::CRTP
派生的任何类
它必须与模板演绎进行一些交互,因为对于mine::ItWorks
:一个不使用CRTP的简单结构,一切都按预期进行
但是,gcc 5.1.0和clang 3.5.1都同意我的观点,并正确编译了代码。这看起来像是一个VS2013错误
有什么想法吗?
谢谢 据我所见,这似乎不是一个bug
template<class _Ty> inline __nothrow bool isnan(_Ty _X)
template<typename A> bool isnan(const Base<A>& x)
然后,您的实现将起作用
根据评论更新
isnan
可能位于全局命名空间(来自math.h)中,而不仅仅位于导致冲突的std(cmath)中。- 这一定与模板推导有关,因为如果我在名称空间mine
中添加重载bool isnan(const-Derived&x)
,那么一切都会正常工作。需要明确的是,为每个函数和从“mine::CRTP”派生的每个类添加重载不是可行的解决方案,由于有许多函数和许多派生类…:(我刚刚发现“允许一个实现[…]进入全局名称空间”,我一直认为isnan在名称空间std中。现在你的答案是有道理的。如果你说清楚这一点(isnan可能在全局名称空间中),我会接受你的答案。
template<class _Ty> inline __nothrow bool isnan(_Ty _X)
template<typename A> bool isnan(const Base<A>& x)
bool isnan(Derived _X)
bool isnan(const Base<Derived>& x)
template <typename A>
int fpclassify(const Base<A>& x)
{
return ::fpclassify(x.value());
}