std::min/max类型扣除在Linux和Windows上不同
std::min/max type deduction different on linux and windows
在下面的代码中,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
的运算符[]是
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);
那么,为什么海湾合作委员会要在这里纾困呢?
VS2013 上的错误:
error C2782: 'const _Ty &std::max(const _Ty &,const _Ty &)' : template parameter '_Ty' is ambiguous
C:Program Files (x86)Microsoft Visual Studio 12.0VCincludealgorithm(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
,所有代码都按预期工作!全局命名空间中讨厌的双层地板(...(函数!
如果它不是拼写错误,那么在此语句中
int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0);
整数文本9.9
具有类型 double
,而其他操作数具有浮点类型。因此编译器无法决定是使用模板参数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,它将返回类型为double
的标准C函数floor
放在全局命名空间中。
double floor(double x);
因此,应用此函数后的操作数将转换为双精度类型。 但似乎 MS VC++ 没有将此函数放在全局命名空间中,或者 MS VC++ 中的全局命名空间具有同名的重载函数。
因此,问题与每个编译器在全局命名空间中放置的函数floor
有关。
我认为如果您使用限定名称std::floor
那么 GCC 也会发出错误。
所以在你的代码中 MS VC++ 使用函数
float floor(float x);
结果在GCC使用功能时发出错误
double floor(double x);
并且函数std::max
的所有操作数都具有类型double
,并且代码编译成功:)
因此,可能让您感到困惑的是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>
一样。就我个人而言,在包含将在我的所有项目中包含该标题的<windows.h>
或标题之前,我会做#define NOMINMAX
,这样我就会得到"标准"行为。例如,这是我在 DirectX 工具包中使用的预编译标头:
#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>
......
根据我记得在GCC-4.8的数学实现中,floor函数返回double
。这就是问题所在。尝试显式投射到浮点数或尝试使用您自己的floor
。
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 在Linux for Windows上编译C++代码时出错
- 在Linux和C++中的Windows上,散列字符串值会产生不同的输出
- 函数在Windows或Linux上运行时表现不同
- 如何在CPP中创建应该在Windows和Linux上运行的套接字?
- CMake WxWidgets项目成功地在Linux上构建,但没有在Windows上构建
- 声明C++具有动态大小的数组类型在 Linux 中工作正常,但不能在 Windows 中工作
- 如何在 Linux for Windows 上通过 MinGW 构建静态 ICU 的 Boost
- 在Linux上使用Clang / OLLVM交叉编译helloworld Windows可执行文件时的问题
- 分段 Linux Ubuntu 中的 g++ 错误,但在 Windows 中的 g++/MingW 中,在 C++ 中打
- 如何在Linux / Windows操作系统上使用文件*.cpp一步编译下面的代码
- 获取块设备 Linux/Windows 的大小
- 奇怪!Linux & Windows VSprintf float num to file
- 在 Linux/Windows 上使用 c++ 的 GUI 应用程序
- C++websockets服务器/客户端跨平台linux/windows
- 交叉编译 linux-->windows:使用 opengl32 获得更新的 OpenGL 支持.dll
- 在没有文件支持的情况下保留共享内存(Linux/Windows) (boost::interprocess)
- 如何在Linux/Windows机器的Android操作系统上运行c++程序
- 链接错误- Oculus Rift lib在Qt和VS2013 (Linux - Windows)
- Linux/windows睡眠时间