解决编译器错误

kas*_*sak 5 c++ templates visual-studio compiler-bug

我们有很大的计算几何库。它的内核有问题。我们有定义标量 taits 和自由函数形式的辅助访问器,可以简单地编写cg::epsilon<T>()而不是cg::scalar_traits<T>::epsilon. 但问题是,在 vs2008 和 vs2010 下,它有时会争论它无法推断出Tin 的模板参数cg::epsilon<T>。在 LWS 的其他编译器上工作正常。

重现的简化版本:

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;
}
Run Code Online (Sandbox Code Playgroud)

是否有一些解决方法可以使访问器正常工作?

PS:我们使用cg::scalar_traits<S>::epsilon(), 这有助于发生错误,但是太冗长了

研究:甚至宣称

template<class S>
bool eq(S a, S b, S eps = cg::epsilon<double>())
Run Code Online (Sandbox Code Playgroud)

编译器抱怨他无法为 cg::epsilon 推导出 S。

Cas*_*eri 1

我的猜测是编译器S eps = cg::epsilon<S>()在推导中使用默认参数S。为此,它需要查看 的声明,cg::epsilon<S>()但目前它还不知道S

解决方法是避免第三个参数的默认值并添加两个不同的重载:第一个采用三个参数(abeps),第二个仅采用两个(ab)。后者epscg::epsilon<S>()(此时S已经被推导)获取并将调用委托给前者,如下代码所示:

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);
}
Run Code Online (Sandbox Code Playgroud)