Std :: min / max deduction is different from linux and windows

In the following code, the template type output for std :: min / max seems strange, and I would like to know why and how to fix it correctly.

On Windows VS2013, the following actions are performed and compilation on GCC-4.8 is given: (see below for an error)

int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0f); 

And this compiles on GCC-4.8, but gives compilation on VS2013: (see below for the error)

 int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0); 

v[1-3] are cv::Vec3f v1, v2, v3;

from OpenCV, cv :: Vec3f is the operator of Vec<float, 3> and Vec [] is

 const _Tp& operator [](int i) const; _Tp& operator[](int i); 

Min / max / floor / ceil from the std :: names space (i.e. using std::min , etc. at the top of the code).

So when I write

 int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0f); 

types must be

 max(min(float, min(float, float), float); 

So why is GCC helping out here?

Error 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' 

Error in GCC-4.8:

 error: no matching function for call to 'max(const double&, float)' 

Answer:

GCC did not use std :: floor, but floor from the global namespace (cmath pulled in). If I add using std::floor , all the code works as expected! A loose double floor function (...) in the global namespace!

+6
source share
3 answers

If this is not a typo, then in this statement

 int minX = max(min(floor(v1[0]), min(floor(v2[0]), floor(v3[0]))), 0.0); 

the integer literal 9.9 is of type double , while the other operands are of type float. Therefore, the compiler cannot decide whether to use the template argument float or double

The error message states that for the function

 'const _Ty &std::max(const _Ty &,const _Ty &)' 

there could be 'double' or 'float'

This function call looks like

 std::max( float_value, double_value ); 

You can explicitly specify a template argument, for example,

 std::max<double>( float_value, double_value ); 

or

 std::max<float>( float_value, double_value ); 

As for GCC, it puts the standard C floor function, which has a double return type in the global namespace.

 double floor(double x); 

Thus, operands after applying this function are converted to type double. But it looks like MS VC ++ does not put this function in the global namespace or the global namespace in MS VC ++ has overloaded functions with the same name.

So the problem is which floor function each compiler fits into the global namespace.

I think that if you used the qualified name std::floor , then GCC will also throw an error.

So, in your code, MS VC ++ uses the function

 float floor(float x); 

and the result is an error, and GCC uses the function

 double floor(double x); 

and all operands of the std::max function are of type double , and the code compiled successfully. :)

+2
source

From what I remember in the mathematical implementation in GCC-4.8, the floor function returns double . This is problem. Try explicitly overlaying the float or try using your own floor .

0
source

So, something that probably confuses you is a terrible hack in the titles of the Windows platforms that have been there for ages:

From the depths of 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 

This means that, in all likelihood, your Windows build is probably using macroC # define, not the <algorithm> min / max, as you think.

If you explicitly use std::min or std::max , this will avoid expanding the macro, like max<T> and min<T> . Personally, I bet #define NOMINMAX before including <windows.h> or headers that will include this header in all my projects, so I get the "standard" behavior. For example, this is the Precompiled Header, which I use in the 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> ... 

See KB 143208

Of course, this suggests that the module in question somehow pulled <windows.h> ...

0
source

Source: https://habr.com/ru/post/973241/


All Articles