|
Here, the number of times that a is incremented before calling f depends on what it is being compared with!
Fortunately, you don’t need to put up with this nonsense. You can get all the efficiency of a macro plus all the predictable behavior and type safety of a regular function by using a template for an inline function (see Item 30): - template
- inline void callWithMax(const T& a, const T& b)
{ f(a > b a : b); }
This template generates a whole family of functions, each of which takes two objects of the same type and calls f with the greater of the two objects. There’s no need to parenthesize parameters inside the function body, no need to worry about eva luating parameters multiple times, etc.
Furthermore, because callWithMax is a real function, it obeys scope and access rules. For example, it makes perfect sense to talk about an inline function that is private to a class. In general, there’s just no way to do that with a macro.
Given the availability of consts, enums, and inlines, your need for the preprocessor (especially #define) is reduced, but it’s not eliminated. #include remains essential, and #ifdef/#ifndef continue to play important roles in controlling compilation. It’s not yet time to retire the preprocessor, but you should definitely give it long and frequent vacations.
Things to Remember
For simple constants, prefer const objects or enums to #defines.
For function-like macros, prefer inline functions to #defines.
|