Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are C++ macros beneficial? [closed]

People also ask

When should you use macros in C?

In C, the macro is used to define any constant value or any variable with its value in the entire program that will be replaced by this macro name, where macro contains the set of code that will be called when the macro name is used in the program.

What is a purpose of C macros?

The Concept of C Macros Macros are generally used to define constant values that are being used repeatedly in program. Macros can even accept arguments and such macros are known as function-like macros. It can be useful if tokens are concatenated into code to simplify some complex declarations.

Should you avoid macros in C++?

A quick google for "Why should I avoid macros in C++" brought up this: securecoding.cert.org/confluence/display/cplusplus/… Well, you should avoid using a macro where some other feature provides a better alternative; otherwise use a macro.


As wrappers for debug functions, to automatically pass things like __FILE__, __LINE__, etc:

#ifdef ( DEBUG )
#define M_DebugLog( msg )  std::cout << __FILE__ << ":" << __LINE__ << ": " << msg
#else
#define M_DebugLog( msg )
#endif

Methods must always be complete, compilable code; macros may be code fragments. Thus you can define a foreach macro:

#define foreach(list, index) for(index = 0; index < list.size(); index++)

And use it as thus:

foreach(cookies, i)
    printf("Cookie: %s", cookies[i]);

Since C++11, this is superseded by the range-based for loop.


Header file guards necessitate macros.

Are there any other areas that necessitate macros? Not many (if any).

Are there any other situations that benefit from macros? YES!!!

One place I use macros is with very repetitive code. For example, when wrapping C++ code to be used with other interfaces (.NET, COM, Python, etc...), I need to catch different types of exceptions. Here's how I do that:

#define HANDLE_EXCEPTIONS \
catch (::mylib::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e); \
} \
catch (::std::exception& e) { \
    throw gcnew MyDotNetLib::Exception(e, __LINE__, __FILE__); \
} \
catch (...) { \
    throw gcnew MyDotNetLib::UnknownException(__LINE__, __FILE__); \
}

I have to put these catches in every wrapper function. Rather than type out the full catch blocks each time, I just type:

void Foo()
{
    try {
        ::mylib::Foo()
    }
    HANDLE_EXCEPTIONS
}

This also makes maintenance easier. If I ever have to add a new exception type, there's only one place I need to add it.

There are other useful examples too: many of which include the __FILE__ and __LINE__ preprocessor macros.

Anyway, macros are very useful when used correctly. Macros are not evil -- their misuse is evil.


Mostly:

  1. Include guards
  2. Conditional compilation
  3. Reporting (predefined macros like __LINE__ and __FILE__)
  4. (rarely) Duplicating repetitive code patterns.
  5. In your competitor's code.