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

Traits of void resolved

It looks like I’ve got clarified status of the traits of void type. I posted my question to libstdc++ where Paolo Carlini kindly provided me what the bits I have been missing. Now, all the puzzles are in place:

[n1836], the specifications for the TR1 features mandates true for is_pod<void>, etc. Arguably this is a defect, which has been fixed in the ongoing work for the next standard, so-called C++0x.

The TR1 document in section 4.9 states:

8 It is unspecified under what circumstances, if any, is_pod::value evaluates to true, except that, for all types T:

is_pod<T>::value >=
   (is_scalar<T>::value || is_void<T>::value);

Given that, the bug report ID:458570 I submitted to Visual C++ 9.0 and it’s TR1 implementation on Microsoft Connect stays valid and according to what Stephan T. Lavavej confirmed in comments to my report, it’s been fixed in Visual C++ 10.0.

Paolo also added a note particularly important to programmers relying on C++ implementation by GCC compiler and libstdc++ library:

In general, we consider TR1 essentially frozen at this time and minimally maintained, consider that it was just an interim Technical Report

Here are references that are fundamental for the matter:

  • n1836 – Draft Technical Report on C++ Library Extensions
  • n2960 – Working Draft, Standard for Programming Language C++
  • Implementation of is_pod<T> and the rest of type traits by Boost.TypeTraits library.

Mission accomplished ;-)

Traits of void

Long time ago, I reported bug to Visual C++ 9.0 (Visual Studio 2008 SP1) complaining that has_trivial_destructor applied to void returns true (ID:458570). I also discussed it with folks on comp.std.c++ where, among quite different voices, Pete Becker writes:

[tr.meta.req]/8 in TR1 requires is_pod::value to be 1. n2857 is not a standard, and implementations of previous standards are not wrong for not doing what isn’t yet required of them.

and later concludes:

Under the current standard, using the name std::is_pod requires a diagnostic. So if you want to be literal, both compilers are “wrong”. Nevertheless, neither is really “wrong”, they just implement different non-standard versions of is_pod.

So, Visual C++ might actually not be wrong. Fair enough.

Today, I got back to this issue for a while a little extending my test program to use the type traits from both, TR1 and C++0x:

#include <iostream>
#include <tr1/type_traits>
int main()
{
using std::cout; using std::endl;
cout << std::tr1::is_pod<void>::value << endl;
cout << std::tr1::has_trivial_destructor<void>::value << endl;
cout << std::is_pod<void>::value << endl;
cout << std::has_trivial_destructor<void>::value << endl;
}

and compiled it with GCC 4.4.1:

$ g++ -Wall -pedantic -std=c++0x void.cpp
$ ./a.out
1
1
0
0

Now, my confusion has been raised to the power of 2. This is clearly a Polnische Wirtschaft or Czech movie or Turkish sermon

…let’s try to ask libstdc++ folks.

Iterators Must Go!

I’ve already announced the brilliant and provocative presentation given by Andrei Alexandrescu titled Iterators Must Go!.

Here is video of Andrei’s keynote digged to boostcon.blip.tv:

It may seem this is a C++ oriented presentation, but in fact it’s more related to software design, design patterns and idioms, interface oriented design, programming by contract and…shortly, it’s really worthwhile to watch, during lunchtime of course ;-), and enjoy!

Got new toy

I’ve just got new toy tool. Since yesterday, I’m a happy owner of the most standards-conformant C++ compiler that ever existed – Comeau C/C++ from Comeau Computing.

I’ve successfully installed Comeau C/C++ 4.3.10.1 Beta compiler and libcomo36, accompanying Standard C++ Library, on 32-bit version of latest Ubuntu 9.04.

I’m going to use Comeau C/C++ for purposes like analysis and review of C++ source code I write or use, verification of code portability as well as for learning elements of C++ and experimenting. This is excellent compiler for learning C++ language. Among loads of features, one of the coolest is ability to give clear and informative error messages. This is very helpful while working with complex class and function templates.

Continue reading

std::basic_istream fixed in VC++ 9.0

Stephan T. Lavavej from the Visual C++ Libraries Development Team confirmed that the bug I’ve reported recently about incorrect cast in the input operator implemented in the std::basic_istream class has been fixed. New corrected implementation is available in the C++ Standard Library shipped with latest version of the Visual C++ 9.0 compiler from the Visual Studio 2008.