illegal token on right side of ‘::’

libLAS - ASPRS LiDAR data translation toolsetOne 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).