tags:

views:

1407

answers:

21

In our legacy code, as well as our modern code, we use macros to perform nifty solutions like code generations, etc. And we make use of both the # and ## operators.

I am curious how other developers use macros to do cool things, if they use them at all.

+2  A: 

From the CrashRpt project , need trick to widen macros and defines:

#define WIDEN2(x) L ## x 
#define WIDEN(x) WIDEN2(x)
std::wstring BuildDate = std::wstring(WIDEN(__DATE__)) + L" " + WIDEN(__TIME__);
Brian R. Bondy
+1  A: 

When you implement a COM server, you have to take care of all exceptions your code could possibly throw - letting an exception through COM method boundary will often crash the calling application.

Methods brackets are useful for this. There's an opening bracket which is a macro containing "try" and a closing bracket that contains a set of "catch"es, wrapping of exceptions into ErrorInfo and producing HRESULTs.

sharptooth
Or, you could just use try{...}catch().
John Dibling
That's enough for just ignoring the exceptions, but not for translating them. You may want to have several catch-handlers in a row - one for all exceptions derived from a common base, another for everything derived from std::exception - this should all be listed explicitly.
sharptooth
To achieve all this you could copy-paste or use a bracket.
sharptooth
+6  A: 

You can have a look at Boost.Preprocessor to find lot's of interesting uses of the preprocessor...

sth
+1: You beat me to it a couple of seconds!
Subtwo
+10  A: 

Coolest macro is: assert, include guards, __FILE__, __LINE__.
Avoid using other macro in your code.

EDIT:
Use macros only when you don't have legal solution w/o them.

bb
Just some nifty tricks cannot be performed without macros... but delegate in trusted libs for this: boost::for_each, as an example.
David Rodríguez - dribeas
did you mean BOOST_FOR_EACH (macros doesn't support namespaces )? :)but I agree, sometimes (very seldom) macros usage is not avoidable or solutions w/o macros more ugly than with..
bb
Well said. assert because C++ doesn't contain an assert instruction, include guards for practical reasons, but leave everything else aside.
Daniel Daranas
+5  A: 

The main place I use macros is in my own testing framework. For example, when I want to assert that some code must throw, I use this macro:

#define MUST_THROW( expr )                       
  try {                                
    (expr);                              
    (myth_suite_).Fail( #expr +                    
            std::string( " should throw but didn't" ) );  
  }                                  
  catch( ... ) {                            
  }

And use it like this:

MUST_THROW( some_bogus_stuff() );
MUST_THROW( more_bogus_stuff() );

The only other place I use them is in class declarations. I have a macro:

#define CANNOT_COPY( cls )              \
  private:                              \
    cls( const cls & );                 \
    void operator=( const cls & )       \

which I use to specify that a class cannot be copied (or assigned):

class BankAccount {

    CANNOT_COPY( BankAccount );
    ....
};

this doesn't do anything special but draws peoples attention and can easily be searched for.

anon
CANNOT_COPY can be done without macros, just derive from a "noncopyable class" which has private copy ctor and op=.
Which of course makes the inheritance scheme more complicated, and when you need a "real" base class, it unnecessarily increases the size of your class pointers on some compilers.
zildjohn01
It increases the size of pointers? huh... no... and i'm not sure what you mean by inheritance scheme
it adds a vptr to every class instance and possibly introduces issues relating to multiple inheritance
anon
I thought a vptr is created only when there are virtual functions.
A: 

Most (all?) C++ Unit Testing frameworks are built upon macros. We use UnitTest++. Check it out to see all sorts of fancy macros.

Joe
Not all, there's tut-framework.sf.net which is much harder to use than others, because it uses no macros.
+1  A: 

My favourite trick with a macro:

Use a macro - Hey Presto, the code quality disappears!

DJClayworth
+1 for showing the most common sense.
David Thornley
-1 for the uninformative knee-jerk response
Jesse Rusak
Sometimes macros are useful, just so few times...
David Rodríguez - dribeas
Like any tool is only useful if you know how to use it and you use it with caution, so are macros.Often macros increase readability of code thus improving code quality.
qrdl
I'm aware that the use of macros _can_, with caution, improve quality. I would take issue with 'often'.
DJClayworth
A: 

The BOOST_BINARY macro performs some clevel pre-processor trickery to give C++ the ability to express numeric constants in binary. It is limited to 0-255 however.

Ferruccio
http://www.boost.org/doc/libs/1_38_0/boost/utility/binary.hpp - Oh my god that is the most hideous header I have ever seen.
dreamlax
A: 

The pthreads utility macros are particularily impressive IMHO.

dsm
A: 

When i work on huge c/c++ nested structures like the one used for 3GPP RRC/NBAP/RNSAP, i follow this trick to make the code look clean.

struct leve1_1
{
  int data;

  struct level2
  {
    int data;

    struct level3
    {
      int data;
    } level_3_data;

  } level_2_data;

} level_1_data;

level_1_data.data = 100;

#define LEVEL_2 leve1_1_data.level_2_data
LEVEL_2.data = 200;

#define LEVEL_3 LEVEL_2.level_3_data
LEVEL_3.data = 300;

#undef LEVEL_2
#undef LEVEL_3

This will make life easier during maintenance time..also in design time and code will be readable.

Warrior
John Dibling
And it makes it hell to run a debugger on the code; the debugger wants the expanded name, but that isn't visible in the source it shows you.
Jonathan Leffler
You also need to ask yourself whether the code is violating the Law (Rule?) of Demeter.
Jonathan Leffler
you guys wil get surprised, if i say this. I inherited this macro usage technique from a code base Provided by Bell Labs .... I find it extremely useful. I think this may be a context sensitive trick.
Warrior
Not surprised at all. Even the most respected among us are more than capable of churning out horrible code.
John Dibling
+4  A: 

Logging is one place where macros are particulary often used:

#define LOG(log) \
  if (!log.enabled()) {} \
  else log.getStream() << __FILE__ << "@" << __LINE__ << ": "


log_t errorlog;
...

LOG(errorlog) << "This doesn't look good:" << somedata;
sth
I believe your empty block could just as well be a semicolon and that would still be valid, and arguably cleaner/more consistent.
Chris Lutz
+7  A: 

In C, it's common to define macros that do some stuff getting the verbatim argument, and at the same time define functions to be able to get the address of it transparently.

// could evaluate at compile time if __builtin_sin gets
// special treatment by the compiler
#define sin(x) __builtin_sin(x)

// parentheses avoid substitution by the macro
double (sin)(double arg) {
    return sin(arg); // uses the macro
}

int main() {
    // uses the macro
    printf("%f\n", sin(3.14));

    // uses the function
    double (*x)(double) = &sin;

    // uses the function
    printf("%f\n", (sin)(3.14));
}
Johannes Schaub - litb
Whoa! What's up with the (sin)? Do you have a reference for this preventing macro expansion? I've never heard of this.
Jesse Rusak
jder, indeed the C (and C++) standard says replacement for a function like macro is done only if there is a ( immediately following the macro name. if there is a ) like in our case, no replacement is done :) 6.10.3/10 in C99 TC2 (doc n1124 here). there's an example in 7.1.4 as a footnote of this.
Johannes Schaub - litb
Neat, thanks. I also didn't know you could put parens in a function declaration.
Jesse Rusak
Very nice trick. I've come across maybe one or two situations where this would be useful.
strager
+6  A: 

There is also the X Macro idiom which can be useful for DRY and simple code generation :

One defines in a header gen.x a kind of table using a not yet defined macro :

/** 1st arg is type , 2nd is field name , 3rd is initial value , 4th is help */
GENX( int , "y" , 1 , "number of ..." );
GENX( float , "z" , 6.3 , "this value sets ..." );
GENX( std::string , "name" , "myname" , "name of ..." );

Then he can use it in different places defining it for each #include with a usually different definition :

class X
{
public :

     void setDefaults()
     {
#define GENX( type , member , value , help )\
         member = value ;
#include "gen.x"
#undef GENX
     }

     void help( std::ostream & o )
     {
#define GENX( type , member , value , help )\
          o << #member << " : " << help << '\n' ;
#include "gen.x"
#undef GENX
     }

private :

#define GENX( type , member , value , help )\
     type member ;
#include "gen.x"
#undef GENX
}
Very nice.......
I've seen this a lot, and used it, too. it's not pretty, but it's a good technique for where reflection would otherwise be useful.
Jesse Rusak
In classic macro assembler coding, this kind of trick is used a lot. Even in C, it can really clarify table generation, especially for tables where some rows have different content than others. The machinations that MFC uses to build message handler tables are a good example of that.
RBerteig
+7  A: 

One of my favorite tricks is a way to pass variable number of arguments to macros, to be later used in calling printf-like functions for example. To do this, I specify that the macro has only one parameter and use it in the body of the macro without (), but pass all the parameters to the macro in (( and )), so the list looks like a single argument. For example,

#define TRACE( allargs) do { printf allargs; } while ( 0)
...
TRACE(( "%s %s\n", "Help", "me"));
dmityugov
You can also use __VA_ARGS__ in c99, which looks nicer at the caller.
Jesse Rusak
I believe something like this is going into C++0x, also.
David Thornley
+3  A: 

SHOW() for debugging:

#define SHOW(X) cout << # X " = " << (X) << endl


The double-evaluation to expand the arguments trick: (E.g. Use the actual line number and not "__LINE__".)

    /* Use CONCATENATE_AGAIN to expand the arguments to CONCATENATE */
#define CONCATENATE(      x,y)  CONCATENATE_AGAIN(x,y)
#define CONCATENATE_AGAIN(x,y)  x ## y


Static compile-time assertions.
E.g.:

#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]

Used via:

typedef  int32_t  int4;

STATIC_ASSERT( sizeof(int4) == 4, sizeof_int4_equal_4 );


Initializing an instance of class CodeLocation: (Storing File/Line/Function from the point of invocation -- this can *ONLY* be done with a macro or by directly accessing the __FILE__/__LINE__/etc macros at the source point.)

        /* Note:  Windows may have __FUNCTION__.  C99 defines __func__. */
#define CURRENT_CODE_LOCATION()  \
           CodeLocation( __PRETTY_FUNCTION__, __FILE__, __LINE__ )


Subsequently used by MESSAGE/WARN/FAIL macros as a convenient source-location printing mechanism. For example:

#define WARN_IF_NAN(X)                                      \
  do                                                        \
  {                                                         \
    if ( isnan(X) != 0 )                                    \
      WARN( # X " is NaN (Floating Point NOT-A-NUMBER)" );  \
    if ( isinf(X) != 0 )                                    \
      WARN( # X " is INF (Floating Point INFINITY)" );      \
  } while ( false )


Assert/Unless macros. You can pass any token, including operators like '==', through a macro. So constructs like:

ASSERT( foo, ==, bar )

Or

UNLESS( foo, >=, 0, value=0; return false; );

Are legal. Assert/Unless macros can automatically add all sorts the nice useful info like CodeLocation, stack traces, or throwing exceptions / coredumping / exiting gracefully.


Making errno simplier:

#define ERRNO_FORMAT  "errno= %d (\"%s\")"
#define ERRNO_ARGS    errno, strerror(errno)
#define ERRNO_STREAM  "errno= " << errno << " (\"" << strerror(errno) << "\") "

E.g. printf( "Open failed. " ERRNO_FORMAT, ERRNO_ARGS );

Mr.Ree
+1  A: 

Converting them to a construct of the language to improve type safety and debugging ability.

JohnMcG
+2  A: 

One can simplify repetitive things for ie. enum lists

enum {
  kOneEnum,
  kTwoEnum,
  kThreeEnum,
  kFourEnum
};

...and later do a switch case over a structured way

#define TEST( _v ) \
    case k ## _v ## Enum: \
      CallFunction ## _v(); \
      break;

switch (c) {
    TEST( One   );
    TEST( Two   );
    TEST( Three );
    TEST( Four  );
}

Note: Sure this could be done with a function pointer array but this opens for a little more flexibilities to add parameters and also use the string expansions with the single hash.

...or to test on strings to get the right enum value

int value = -1;
char *str = getstr();

#define TEST( _v ) \
    if (!strcmp(# _v, str)) \
        value = k ## _v ## Enum

TEST( One   );
TEST( Two   );
TEST( Three );
TEST( Four  );
epatel
+1  A: 

I often wrap things like debug sonar in a simple macro that allows it to be compiled out of release builds:

#ifdef DEBUG
#define D(s) do { s; } while(0)
#else
#define D(s) do {/**/} while(0)
#endif

Usage later is typically something like:

D(printf("level %d, condition %s\n", level, condition));

The do{}while(0) idiom is there to avoid issues that might result from accidentally making a usage of D(...) the only content of a conditional or loop. You don't want code like this to mean the wrong thing, after all:

for(i=1;i<10;++i) D(printf("x[%d]=%f\n",i,x[i]));
SomeReallyExpensiveFunction(x);

If I could make that case throw an error, I would, but the preprocessor would have to be a full compiler itself to tell that the D() macro was the sole content of a loop body.

I'm also a big fan of compile-time assertions. My formulation is slightly different, but has no real advantages over others I've seen. The key is to form a uniquely named typedef that throws an error if the asserted condition is false, and not otherwise. In cassert.h we have:

/*! \brief Compile-time assertion.
 *
 *  Note that the cassert() macro generates no code, and hence need not
 *  be restricted to debug builds.  It does have the side-effect of
 *  declaring a type name with typedef.  For this reason, a unique
 *  number or string of legal identifier characters must be included
 *  with each invocation to avoid the attempt to redeclare a type.
 *
 *  A failed assertion will attempt to define a type that is an array
 *  of -1 integers, which will throw an error in any standards
 *  compliant compiler. The exact error is implementation defined, but
 *  since the defined type name includes the string "ASSERTION" it
 *  should trigger curiosity enough to lead the user to the assertion
 *  itself.
 *
 *  Because a typedef is used, cassert() may be used inside a function,
 *  class or struct definition as well as at file scope.
 */
#define cassert(x,i) typedef int ASSERTION_##i[(x)?1:-1]

And in some source file, anywhere a typedef would be legal:

#include "cassert.h"
...
cassert(sizeof(struct foo)==14, foo1);
...

The resulting error message is often obscure, but will contain the fragment of identifier enabling the offending line to be discovered by brute force.

I've been guilty of using the preprocessor in places where writing a code generation utility might have been the preferred answer, much like the code in another answer that generated lots of boiler-plate based on the unique parts of an enum member's name. That is especially handy when writing a lot of message-dispatch glue to be compiled in C.

RBerteig
+1  A: 

I credit Sean Barrett for this fun one:

#ifndef blah
#define blah(x) // something fun
#include __FILE__
#undef blah

#ifndef blah
#define blah(x) // something else that is also fun
#include __FILE__
#undef blah

#ifdef blah
blah(foo)
blah(bar)
#endif

A hacky way to get the preprocessor to generate code for you based on some higher level structure that you can express through macros.

MSN
A: 
void _zero_or_die(int v, const char* filename, int line)
{
    if (v != 0)
    {
       fprintf(stderr, "error %s:%d\n", filename, line);
       exit(1);
    }
}

#define ZERO_OR_DIE_ for (int _i=1; _i == 1; _zero_or_die(_i, __FILE__, __LINE__)) _i=



ZERO_OR_DIE_   pipe(fd);
ZERO_OR_DIE_   close(0);
ZERO_OR_DIE_   sigaction(SIGSEGV, &sigact, NULL);
ZERO_OR_DIE_   pthread_mutex_lock(&mt);
ZERO_OR_DIE_   pthread_create(&pt, NULL, func, NULL);
Adrian Panasiuk
A: 

On micro controllers it is common to debug code using UART, as hardware breakpoints have many drawbacks.

This is a simple macro that has proven very useful:

#define DEBUG_OUT(value) sprintf(uartTxBuf, "%s = 0x%04X\n", #value, value);\
                         puts_UART((uint16_t *) uartTxBuf)

Usage example:

for (i=0; i < 4; i++)
{
    DEBUG_OUT(i);
    DEBUG_OUT(i % 3);
}

Recieved stream:

i = 0x0000
i % 3 = 0x0000
i = 0x0001
i % 3 = 0x0001
i = 0x0002
i % 3 = 0x0002
i = 0x0003
i % 3 = 0x0000

Yes, it's crude and unsafe. It's only applied until the bug is isolated, so this macro does no harm.

Josip