5

I am fairly familiar with the basics of C++, but lack experience (mainly code in Java), so slightly "dumbed down" replies would be appreciated :)

I am extending a larger open source project, which uses a standard visual studio class limits.h, where the following code can be found:

template<> class numeric_limits<double>
    : public _Num_float_base
    {   // limits for type double
public:
    typedef double _Ty;

    static _Ty (max)() _THROW0()
    {   // return maximum value
        return (DBL_MAX);
    }

I have now imported another open source project, which uses minwindef.h which has this piece of code in it:

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

The build now breaks because for this line

SUMOReal distance = std::numeric_limits<SUMOReal>::max();

the compiler complains about max() being used without any parameters. Is there any quick way to get around this issue, or can I simply not use the library I imported? :/

Hope this was clear enough, thanks for any suggestions!!

Samuel Neugber
  • 1,041
  • 1
  • 11
  • 17
  • 1
    possible duplicate of [warning C4003 and errors C2589 and C2059 on: x = std::numeric\_limits::max();](http://stackoverflow.com/questions/1904635/warning-c4003-and-errors-c2589-and-c2059-on-x-stdnumeric-limitsintmax) – jrok Oct 16 '13 at 17:11
  • 1
    An that, my friend, is why macros should not be used, and if used should have horrible names that show their horrible nature – David Rodríguez - dribeas Oct 16 '13 at 17:14
  • header files which `#define` `min` or `max` are a sin and should **never be used**. – Walter Oct 16 '13 at 17:17
  • @Walter Agreed. That's why you always compile with `/DNOMINMAX` under Windows. (The macros are a historical artifact, which are still there to avoid breaking legacy code which used them. You shouldn't use them in new code.) – James Kanze Oct 16 '13 at 17:18
  • @jrok Yup, definitely duplicate. Looks like I was searching for the wrong things... – Samuel Neugber Oct 16 '13 at 20:21

3 Answers3

4

The only way to get around the problem is to #undef the macro.

This is one of the reasons that macros traditionally are spelled with all UPPER_CASE letter, while system and standard functions are all lower case.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    The macro is conditionally defined in a Windows header. It's sufficient to compile with the correct options for it to disappear. – James Kanze Oct 16 '13 at 17:17
  • 1
    @JamesKanze I strongly disagree. Going into the details of header files which are recursively `#included` by other header files cannot be sensible. `#undef`ing the macro is perfectly okay. – Walter Oct 16 '13 at 17:20
  • 1
    I have to agree with @Walter and this answer. – John Dibling Oct 16 '13 at 17:24
  • 1
    @Walter It's the `#undef` solution which requires going into the details of the header files (do I need it, etc.). Just set the correct compiler flags (as documented by Microsoft), and it works. – James Kanze Oct 16 '13 at 17:28
4

You can prevent C++ preprocessor for expansion of max macro for the specific line of code and then reenable it after the line. This solution would not affect the other parts of code (i.e. if macro max is needed somewhere else):

#pragma push_macro("max")
#undef max
SUMOReal distance = std::numeric_limits<SUMOReal>::max();
#pragma pop_macro("max")
Igor Popov
  • 2,588
  • 17
  • 20
3

In your compiler settings, have NOMINMAX be defined. This will stop the Windows headers from trying to define the min and max macros. This is the correct way to handle this issue; trying to #undef it is unreliable and error-prone. Search for NOMINMAX for more information on this flag.

You can also do this in a pinch, but don't make it a habit:

SUMOReal distance = (std::numeric_limits<SUMOReal>::max)();
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • @Walter: Easy to forget, easy to misplace, and unnecessary overhead to write every time when a single top-level define will do. – GManNickG Oct 16 '13 at 17:20
  • 2
    Just for the record, if you're using VS, that goes in the property pages, under Configuration Properties->C/C++->Preprocessor; just add it to the Preprocessor Definitions field. – James Kanze Oct 16 '13 at 17:21
  • @JamesKanze I don't use VS, but came across such macro definitions elsewhere. They can be very annoying, in particular as the resulting compiler error message make absolutely no sense. – Walter Oct 16 '13 at 17:23
  • @Walter I know what you mean: I can remember when `` defined a macro `String`. Made compiling with USL very painful. Today, if a library defines such macros for other than historical reasons, and without a documented means of turning them off, I'd say just don't use it. But that's not the case here: the header in question is a Windows header, and Microsoft documents exactly what you should do to avoid the problem. – James Kanze Oct 16 '13 at 17:31