One of my favorite features of C++ is the ability for constructors to run code. This allows for the creation of some interesting objects whose sole purpose is only to run a little bit of code. Here is an example:
#define SAY_WORD( WORD ) \
WORD##WordSayer( #WORD );
WordSayer( const char *word )
printf( "%s", word );
Using this SAY_WORD macro is quite easy. It can be placed at global scope anywhere in a cpp file, and the word it contains will indeed be said.
Important registration operations can be performed by global objects like the one above. Often times the global registrator object may never even be referenced in the program as its only purpose is to perform some registration upon program start. This is perfectly fine if you’re working in Visual Studio with a single project in your solution. The problem is when you want to start spreading code over multiple projects. Microsoft’s linker is quite over-zealous and strips away objects that don’t seem to be referenced anywhere throughout the entire solution.
A way to force linking of such objects is needed in order to ensure that global registration objects aren’t stripped by the linker. As a result of such need I came up with a compiler-specific solution that works for all my needs on Visual Studio 2010 and 2012 (probably works with earlier versions too).
#define DECLARE_OBJECT( TYPE ) \
extern "C" Object<TYPE> TYPE##Object; \
__pragma( comment ( linker, "/INCLUDE:_"__STRINGIZE( TYPE##Object ) ) )
The above macro can be placed into a header and it will force the compiler to link the object. In order to force linking the linker flag /INCLUDE needs to be used. However, the name of the symbol representing an object is required to be passed in. In Visual Studio a single underscore is appended to object names, and a stringizing macro can be used to generate the name of whatever global variable you’re instantiating.
To further ensure that the macro works I tried to prevent any C++ name mangling by externing the object as a C style object.
I have made prolific use of this style of macro in my custom C++ reflection, along with factory registration, along with some other things. Hopefully this trick can be of use to others as well.