Следующий упрощенный код не компилируется в 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;
}
Ошибка:
c:\program files (x86)\microsoft visual studio 12.0\vc\include\math.h(425): error C2665: 'fpclassify' : none of the 3 overloads could convert all the argument types
could be 'int fpclassify(long double)'
or 'int fpclassify(double)'
or 'int fpclassify(float)'
while trying to match the argument list '(mine::Derived)'
Я ожидал, что ADL вызовет mine::isnan()
при вызове mine::Derived
, но по какой-то причине VS2013 пытается вызвать функцию шаблона isnan()
из глобального пространства имен.
Конечно, если я вызываю mine::isnan()
напрямую, все работает правильно, но это не решает моей проблемы, потому что мне нужно вызывать isnan()
в шаблонном контексте, где я могу получить double
или любой другой класс, производный от mine::CRTP
.
Должно быть какое-то взаимодействие с выводом шаблона, потому что для mine::ItWorks
все работает так, как ожидалось: простая структура, не использующая CRTP.
Однако gcc 5.1.0 и clang 3.5.1 согласны со мной и правильно компилируют код. Это похоже на ошибку VS2013...
Любые идеи? Спасибо!
bool isnan(const Derived& x)
в пространство именmine
то все будет работать. - person dats   schedule 13.05.2015