Boost.Geometry and macros made by Apple

Boost Geometry (aka Generic Geometry Library, GGL)I have no pleasure continuing my macros are evil tales but the life of C++ programmer eagerly wants to writes add another chapter to the story. Today, it’s time to rant on Apple and its XCode.

One of Boost Geometry (aka GGL) users, Mark, reported that he can not compile his program using the library with GNU C++ compiler from XCode. The compiler throws mysterious complain of a very low-level nature of C++ programming language:

Expected unqualified-id before 'do' in
/usr/local/include/boost_1_42_0/boost/geometry/geometries/concepts/check.hpp

Thanks to follow-up by Stjepan we quickly know who to blame for that. It is XCode header AssertMacros.h. It even might be one of public headers from development package of XNU, the Mac OS X kernel, what’s even more fun.

What actually happens that causes the problem?

Boost Geometry defines function template for concept checking:

template <typename Geometry>
inline void check()
{
    detail::checker<Geometry, boost::is_const<Geometry>::type::value> c;
    boost::ignore_unused_variable_warning(c);
}

Apple XCode defines macro using exactly the same name as the function check. The C++ preprocessor, which operates before compiler, substitutes the name check with content of the macro. For the Boost Geometry function check it means that a pile of garbage is injected in place were the function name is expected:

template <typename Geometry>
inline void do { if ( __builtin_expect(!(), 0) ) { DebugAssert('?*?*',
0, "Third Party Client" ": " "", 0, 0, "/usr/local/include/boost/
geometry/geometries/concepts/check.hpp", 181, (void*)0); } } while ( 0 )
{
     detail::checker::type::value> c;
     boost::ignore_unused_variable_warning(c);
}

Obviously, it makes compiler to give up to instantiate the check function from the template and to compile it properly.

C/C++ macros are evil, however, not by design but by insanity of programmers. Every macro defined in a public C/C++ header, should be defined using as unique as possible, but still usable name. I wish Apple folks designed their C/C++ macros as unique as they make their hardware products, even if made in China eventually. This particular macro that caused the problems discussed here, could be named to APPLE_XNU_CHECK and life would be easier. Or, given the fact that almost 3000 files using these identifiers live in Boost C++ Libraries only, I probably should say: life would be more productive, efficient and cheaper.

By the way, it’s a known problem @ Boost and it looks Boost Folks are trying to figure out best solution. See ticket #2115 – Avoid bad Apple macros.

…to be continued

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