在下面的代码中,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;
,cv :: Vec3f是Vec<float, 3>
,而Vec
的运算符[]是
const _Tp& operator [](int i) const;
_Tp& operator[](int i);
min / max / floor / ceil来自std :: namespace(即代码顶部的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);
那为什么海湾合作委员会会在这里纾困?
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而是使用全局命名空间(由cmath绘制)。如果我添加using std::floor
,则所有代码都按预期工作!全局命名空间中令人讨厌的双层(...)函数!
答案 0 :(得分:4)
如果在本声明中不是拼写错误
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 &)'
有could be 'double' or 'float'
这就是funcrion调用看起来像
std::max( float_value, double_value );
您可以明确指定模板参数,例如
std::max<double>( float_value, double_value );
或
std::max<float>( float_value, double_value );
对于GCC,它将全局命名空间中返回类型为floor
的标准C函数double
放置..
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
并且代码编译成功。:)
答案 1 :(得分:1)
所以可能让你感到困惑的是Windows平台标题中的一个可怕的黑客攻击已经存在多年了:
从内心深处“ntdef.h”
#ifndef NOMINMAX
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#endif // NOMINMAX
这很可能意味着,您的Windows版本可能正在使用#define宏而不是<algorithm>
的最小/最大值。
如果您明确使用std::min
或std::max
,这将避免宏扩展,max<T>
和min<T>
也是如此。我个人提到#define NOMINMAX
之前要包括<windows.h>
或将在我的所有项目中包含该标题的标题,以便我得到“标准”行为。例如,这是我在DirectX Tool Kit中使用的预编译头:
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#include <d3d11_1.h>
#include <DirectXMath.h>
#include <algorithm>
...
请参阅知识库143208
当然,这假设有问题的模块以某种方式提取<windows.h>
......
答案 2 :(得分:0)
根据我在GCC-4.8的数学实现中的记忆,floor函数返回double
。那就是问题所在。尝试显式转换为float或尝试使用您自己的floor
。