On page 1057 of Programming Principles and Practice Using C++, Second Edition, Bjarne Stroustrup discusses a problem with Function-like macros.
He starts with an example. The macro below:
#define MAX(x, y) ((x)>=(y)?(x):(y))
used in the following line:
double dd = MAX(aa++, 2);
substitutes to become:
double dd = ((aa++)>=(2)?(a++):(2));
About this example, he explains:
On the other hand, not all the parentheses in the world could save the second expansion. The macro parameter
x
was given the valueaa++
, and sincex
is used twice inMAX
,a
can get incremented twice. Don't pass an argument with a side effect to a macro.As it happens, some genius did define a macro like that and stuck it in a popular header file. Unfortunately, he also called it
max
, rather thanMAX
, so when the C++ standard header defines
template<class T> inline T max(T a, T b) {return a<b?b:a;}
the
max
gets expanded with the argumentsT a
andT b
and the compilers sees
template<class T> inline T ((T a)>=(T b)?(T a):(T b)) {return a<b?b:a;}
The compiler error messages are "interesting" and not very helpful. In an emergency, you can "undefine" a macro:
#undef max
.
Bjarne Stroustrup's story sounds like it would be a well-known one in the C++ community, however, I couldn't find anything more written about it online. Bjarne Stroustrup's frustration here suggests that this particular header created backwards compatibility problems developing C++.
What was the header Bjarne refers to in his story?