在下面的代码中,std::min/max 的模板类型推导似乎很奇怪,我想知道为什么以及如何正确修复它。
以下适用于 Windows VS2013,并在 GCC-4.8 上给出编译错误:(错误见下文)
int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0f);
这在 GCC-4.8 上编译但在 VS2013 上给出编译错误:(错误见下文)
int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0);
v[1-3]
是 cv::Vec3f v1, v2, v3;
在 OpenCV 中,cv::Vec3f 是一个 Vec<float, 3>
和 Vec
的 operator[] 是
const _Tp& operator [](int i) const;
_Tp& operator[](int i);
min/max/floor/ceil 来自 std::命名空间(即代码顶部的 using std::min
等)。
所以当我写的时候
int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0f);
类型应该是
max(min(float, min(float, float), float);
那么为什么 GCC 退出这里呢?
VS2013 错误:
error C2782: 'const _Ty &std::max(const _Ty &,const _Ty &)' : template parameter '_Ty' is ambiguous
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\algorithm(4086) : see declaration of 'std::max'
could be 'double' or 'float'
GCC-4.8 错误:
error: no matching function for call to 'max(const double&, float)'
回答:
GCC 没有使用 std::floor,而是使用全局命名空间中的 floor(由 cmath 引入)。如果我添加 using std::floor
,所有代码都按预期工作!全局命名空间中令人讨厌的 double floor(...) 函数!
最佳答案
如果不是拼写错误,那么在这个声明中
int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0);
整数文字 9.9
的类型为 double
而其他操作数的类型为 float。所以编译器无法决定是使用模板参数float
还是double
错误信息说清楚了函数
'const _Ty &std::max(const _Ty &,const _Ty &)'
可能是“double”或“float”
函数调用看起来像
std::max( float_value, double_value );
您可以显式指定模板参数,例如
std::max<double>( float_value, double_value );
或
std::max<float>( float_value, double_value );
对于 GCC 然后它将返回类型为 double
的标准 C 函数 floor
放置在全局命名空间中。
double floor(double x);
所以应用这个函数后的操作数被转换为double类型。但是好像MS VC++并没有把这个函数放到全局命名空间或者MS VC++的全局命名空间有重载的同名函数。
因此,问题与每个编译器在全局命名空间中放置的函数 floor
有关。
我认为如果您使用限定名称 std::floor
那么 GCC 也会发出错误。
所以在你的代码中 MS VC++ 使用函数
float floor(float x);
结果在 GCC 使用函数时发出错误
double floor(double x);
并且函数 std::max
的所有操作数都具有 double
类型并且代码编译成功。:)
关于c++ - std::min/max 类型推导在 linux 和 windows 上不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25086999/