bsobaid
bsobaid

Reputation: 975

Advantages/disadvantages of implementing functions as macros in C++

Is it a good idea to implement business logic functions as macros?

I inherited some legacy C++ code and I find a whole lot of business logic functions are implemented as long cryptic macros.

Is there an advantage of macros over functions? What is the general rationale behind the use of macros?

What kind of logic is best suited for macros?

Here is a simple sample from code

#define INSERT_VALUES(IN,ID,EO)     {\
    double evaluationOutput = EO;\
    int controls = 0;\
    int input_controls = m_input_controls[IN];\
    if(m_value_list[IN].ShouldProcess())\
        {\
        evaluationOutput = m_evaluationOutput[IN];\
        controls = m_controls[IN];\
        }\
    VALUE_EXIST(evaluationOutput,controls,input_controls,IN,ID,Adj);\
    m_evaluationOutput[IN] = controls > 0 ? evaluationOutput : 0.0;\
    m_controls[IN] = controls;\
    m_input_controls[IN] = input_controls;\                                 
}

Upvotes: 4

Views: 7802

Answers (3)

Gnawme
Gnawme

Reputation: 2389

In Effective C++, Scott Meyers notes in Item 2:

Prefer consts, enums, and inlines to #defines

Specifically referring to the practice of writing macros instead of functions, Meyers says:

Another common (mis)use of the #define directive is using it to implement macros that look like functions but don't incur the overhead of a function call.

Macros like this have so many drawbacks, just thinking about them is painful.

Fortunately, you don't have 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.

[Real functions] obey 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.

To answer your questions specifically:

  • Some programmers write macros instead of functions to avoid the perceived overhead of a function call -- a dubious practice that often has little measurable benefit.
  • Programmers used to use the preprocessor to generate boilerplate code (and perhaps still do). In modern C++, use of the processor should be limited to #include and (maybe) #ifdef/#ifndef for conditional compilation.

As Meyers notes in closing:

It's not yet time to retire the preprocessor, but you should definitely give it long and frequent vacations.

Upvotes: 9

Bruce
Bruce

Reputation: 2310

Long, cryptic anything is not good. If the macros exist for performance issues, you can achieve the same result with inline functions. If they are used for simplifying expressions, they could be refactored to be less cryptic and more easily maintained, if you have time and money for such an endeavor.

Upvotes: 2

ssube
ssube

Reputation: 48267

No. They are absolutely not a general replacement for functions.

Macros are capable of things that the code itself is not, particular creating and modifying tokens (code) prior to compilation.

In exchange, they lose all type safety, and almost all syntactic sugar that may be available for actual code.

When you must do something that can't be done by code, or need code to exist conditionally (super-debug stuff like memory tracing), macros come in handy. They also have some value in providing more concise or more readable ways to do a particular thing (a common example is #define SUCCESS(x) (x >= 0). However, for anything requiring type-safety, exception-catching, or consisting of often-used code that doesn't have to mutate at compile-time, they are almost never appropriate. Most code that seems like it could be a macro can probably be more safely expressed in actual code, which is important for business logic.

The closest rule of thumb you can get is whether something needs to happen or change during compilation. If so, consider a macro, otherwise just code it up. Remember, templates count as code and can do quite a few things you might be tempted to use a macro for, but can be somewhat safer.

Upvotes: 6

Related Questions