C++ Visual Studio 2013中可能存在的ADL错误

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 &

以下简化代码无法在VS2013下编译:

#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());
}