C++ 解决编译器错误

C++ 解决编译器错误,c++,visual-studio,templates,compiler-bug,C++,Visual Studio,Templates,Compiler Bug,我们有一个大的计算几何库。它的内核中有一个问题。我们有标量tait的定义,以及自由函数形式的helper accesor,只需编写cg::epsilon(),而不是cg::scalar\u traits::epsilon。但问题是,在vs2008和vs2010下,它有时会争辩说它不能在cg::epsilon中推导T的模板参数。在LWS中的其他编译器上运行良好 要复制的简化版本: namespace cg { template<class S> S epsilon(); templ

我们有一个大的计算几何库。它的内核中有一个问题。我们有标量tait的定义,以及自由函数形式的helper accesor,只需编写
cg::epsilon()
,而不是
cg::scalar\u traits::epsilon
。但问题是,在vs2008和vs2010下,它有时会争辩说它不能在
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;
}
名称空间cg
{
模板
Sε();
模板
双ε(){return 1;}
模板
float epsilon(){return 1;}
模板
bool eq(sa,sb,S eps=cg::epsilon())
{
返回true;
}
}
int main(int argc,char*argv[])
{
cg::eq(0.0,0.0);
cg::eq(0.0f,0.0f);
返回0;
}
是否有一些变通方法可以让访问者工作

注:我们使用的是
cg::scalar\u traits::epsilon()
,这有助于解决出现错误的地方,但过于冗长

研究: 甚至被宣布为

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

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

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

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

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);
}
模板
布尔均衡(S a、S b、S eps)
{
返回true;
}
模板
布尔均衡(S a,S b)
{
S eps=cg::epsilon();
返回等式(a、b、eps);
}

你的猜测听起来很现实。但是编写包装比使用cg::scalar\u traits::epsilon更糟糕。还有,如果你是对的,为什么使用traits不会触发错误?@kassak:我也不希望像你那样编写包装器并使用默认参数(我相信你的代码符合标准)。编写包装器是一个不必要的解决方法:-(.我不理解你所说的“使用特性不会触发错误”是什么意思,但是,无论如何,我不能确切地说出发生了什么,因为我看不到Visual Studio的代码;-)我只能猜测。是的,我理解。“使用traits不会触发那个错误”我的意思是使用
cg::scalar\u traits::epsilon()
而不是
cg::epsilon()
不会触发那个错误,但是它太冗长了=(
cg::epsilon
只是返回
cg::scalar\u traits::epsilon()
,并且是为了让代码更清晰。因为
cg::epsilon()
不仅更短,它还是S型ε