Macros with halos
The C preprocessor is a notoriously primitive and slippery creature. Included and occasionally embraced by C++, it may eventually prove to be the downfall of the newer language. How much trouble has been caused by seemingly innocuous definitions?
#define min(a, b) (((a) < (b)) ? (a) : (b))
This macro hobbles any attempt to use the standard C++ algorithm, std::min()
, and since it’s a preprocessor thing the compiler warnings may not alert you immediately to what’s going on. You don’t have to include <algorithm>
directly to trigger the problem.
Try compiling this stripped down source file using GCC 3.4.6:
#include <string> #define min(a, b) (((a) < (b)) ? (a) : (b)) #include <sstream>
and you’ll see something like:
In file included from /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/streambuf:781, from /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/ios:50, from /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/istream:45, from /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/sstream:45, from macros.cpp:3: /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/streambuf.tcc: In member function `virtual std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(_CharT*, std::streamsize)': /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/streambuf.tcc:54: error: expected unqualified-id before '(' token /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/streambuf.tcc: In member function `virtual std::streamsize std::basic_streambuf<_CharT, _Traits>::xsputn(const _CharT*, std::streamsize)': /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/streambuf.tcc:88: error: expected unqualified-id before '(' token
I spent a while tracking down a similar problem today (needless to say, the offending macro was hiding several #includes away from the file which triggered the error1). Once I’d exposed the source, I naturally wanted to grumble to someone, so I pasted the code into an instant message to a colleague. Look, my messaging client sanctified the macro by adding halos to the a
’s!
1 One tip for tracking down such problems is to run the preprocessing phase of compilation on its own: with GCC, for example, supply the -E
flag.