One of libLAS users reported that when use of #include <liblas/lasreader.hpp> in his application compiled with Visual C++ 10.0 from Visual Studio 2010 cause this error:
utility.hpp(253): error C2589: '(' : illegal token on right side of '::'
The error is an incarnation of a very well-known problem in Visual C++ when using the C++ Standard Library elements, especially the Standard Template Library, in Windows API-based programs. As libLAS library does use the C++ library, so does a user’s application if includes libLAS headers.
The problem is caused by conflicting definitions of min() and max() macros defined in windef.h header. Macros in C++ are scope-less evil, especially if defined in public headers using such extremely unique names as min or max. The fact that Microsoft defined it way before C++ was born absolves them at large, but for the Spirit sake, they should learn the lesson and disable it for good in C++ mode (but not yet another MS-specific way!). No one who’s sane need or want to use them!
Pie in the sky. In the meantime, C++ programmers as the libLAS user who reported this problem have to deal with it on their own. The easiest way is to check CodeProject or Q143208 or search (not google) for solution like #define NOMINMAX for Visual C++ compiler.
However, is another option is to apply a simple trick to call of *::min() or *::max() functions (i.e. std::min() or std::max() which effectively prevents macro substitution, so the Visual C++ compiler (or any other compiler with similar problem) does not complain about illegal token. The trick is to wrap function name, fully qualified name, with parentheses:
(std::min)(x, y);
In most cases of use of C++ Standard Library as described above, it is required for the following functions:
(std::min)(x, y); (std::max)(x, y); (std::numeric_limits<T>::min)(); (std::numeric_limits<T>::max)();
In case a user-defined type has a member function with exactly the same name as a macro present in global scope (macros always live in global scope!), it may be necessary to apply the very same trick when a member function is called on an object:
template <typename T, int Size>
struct Series
{
T min() { return *(std::min_element(s, s + Size); }
T& operator[](int index) { return s[index]; }
private:
T s[Size];
};
Series<int, 3> s;
s[0] = 2;
s[1] = 3;
s[2] = 1;
int m = (s.min)(); // long way, but here is the trick
There is one side effect which may be an inconvenience. This trick disables argument dependent name lookup (ADL, aka Koenig lookup).
Firstly, global Macros are a godsend. Just because people use them wrongly, badly or incorrectly does not make them bad / “evil” (even if its Microsoft whos using them in the bad way).
Secondly, I am not convinced that the cause you report is correct.
Please post a proof (e.g. small peice of sample code to demonstrait the issue and how the windef.h macros are the issue).
I can definitely agree that VS10 is causing this issue. Hence me arriving at your page, but the min/max macro definitions in windef.h don’t appear related to the issue i’m encountering at all (with the same error output and conditions). I’ll post an article if I get to bottom of cause.
Here is simple program that reproduces the problem:
There is no doubt, the problem and the compilation error is related to the min/max macros defined in Microsoft Visual C++ / Windows API headers.
You can also just put ‘NOMINMAX’ into your pre-processor options
Great tips! lower case macro are very stupid from Microsoft. I try NOMINMAX but some windows include like gdiplus requite this macro…