Mateusz Loskot :: hacking on, working out, living up

illegal token on right side of ::

27 Jan 2010 | mloskot

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);

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]; }
  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).

Fork me on GitHub