Search code examples
c++visual-studiotemplatescompiler-bug

Work around compiler bug


I we have big computation geometry library. There is a problem in it's kernel. We have definitions scalar taits, and helper accesors in form of free functions, to simply write cg::epsilon<T>() instead of cg::scalar_traits<T>::epsilon. But problem that under vs2008 and vs2010 it sometimes argues that it could not deduce template parameter for T in cg::epsilon<T>. On other compilers in LWS works fine.

Reduced version to reproduce:

namespace cg
{

template<class S>
S epsilon();

template<>
double epsilon<double>() {return 1;}
template<>
float epsilon<float>() {return 1;}

template<class S>
bool eq(S a, S b, S eps = cg::epsilon<S>())
{
   return true;
}

}


int main(int argc, char* argv[])
{
   cg::eq(0.0, 0.0);
   cg::eq(0.0f, 0.0f);
   return 0;
}

Are there some workarounds to make accessors work?

PS: We using cg::scalar_traits<S>::epsilon(), that helps, where error occurs, but that too much verbose

Research: Even declarated as

template<class S>
bool eq(S a, S b, S eps = cg::epsilon<double>())

compiler complains that he could not deduce S for cg::epsilon.


Solution

  • My guess is that the compiler is using the defaulted parameter S eps = cg::epsilon<S>() in the deduction of S. For this, it needs to look at the declaration of cg::epsilon<S>() but at this time it doesn't know S yet.

    A workaround is avoiding the default value for the third parameter and add two different overloads: the first takes three arguments (a, b and eps) and the second takes only two (a and b). The latter gets eps from cg::epsilon<S>() (at this time S has already been deduced) and delegates the call to the former as the below code shows:

    template<class S>
    bool eq(S a, S b, S eps)
    {
        return true;
    }
    
    template<class S>
    bool eq(S a, S b)
    {
        S eps = cg::epsilon<S>();
        return eq(a, b, eps);
    }