Related
I am trying to write software that can behave differently based on whether or not a certain component should be simulated in software or execute on real hardware. However, GCC complains that the Scope resolution operator (::) cannot be used in a macro, so my question is: is it possible to define a macro to a static method call?
My goal is to be able to, using another preprocessor define, choose between using all real components (0), using all simulated components (1), or using a mix of real and simulated components (2). This last case is where I am running into this issue. Under this condition, I want to call a function which I am "protecting" by implementing it as a static method. Here is my approach:
#define SIM_CONF 2
#if SIM_CONF == 0
#define IS_HW_SIMULATED(name) false
#define IS_HW_REAL(name) true
#endif
#if SIM_CONF == 1
#define IS_HW_SIMULATED(name) true
#define IS_HW_REAL(name) false
#endif
#if SIM_CONF == 2
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)
#define IS_HW_REAL(name) SimConfig::isReal(name)
#endif
class SimConfig
{
public:
static bool isSimulated(const char* szName);
static bool isReal(const char* szName);
};
EDIT: Here's an example of how I use it elsewhere:
void PumpComponent::commandRevs(float revs)
{
#if IS_HW_SIMULATED("PumpComponent")
// do simulation procedure
#else
// do real hardware procedure
#endif
}
When I compile, GNU Make complains:
error: token "::" is not valid in preprocessor expressions
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)
Is there some approach where I can protect/encapsulate the isSimulated() and isReal() functions, and still be able to refer to them in preprocessor directives?
Problem is how you use this macro. You have placed it as preprocessor #if argument.
Processor do not understand code and argument of #if must be something what processor can handle, so macros and literals.
SimConfig::isSimulated is a code which in not defined yet. It will be know during compilation process, so after preprocessing is completed.
One way to fix it is simply use if else
void PumpComponent::commandRevs(float revs)
{
if IS_HW_SIMULATED("PumpComponent") {
// do simulation procedure
} else {
// do real hardware procedure
}
}
It is not problem for compiler. it will noticed that this is constant and should remove obsolete code.
Other way to fix it is to abandon macros. You can use templates.
Or enclose macro depended stuff in some class and use macros to alter that class functionality (this way this macros will not spread all over your code).
Don't use #if for this. Just write normal code:
void PumpComponent::commandRevs(float revs)
{
if (IS_HW_SIMULATED("PumpComponent")) {
// do simulation procedure
} else {
// do real hardware procedure
}
}
The compiler will delete one of the branches when SIM_CONF is 0 or 1, since the branch condition is a compile-time constant. It will keep the branches when it's 2.
However, I don't see a reason to have the IS_HW_SIMULATED and IS_HW_REAL macros at all. Looking at the code you posted, it seems you only need one function: SimConfig::isSimulated():
bool SimConfig::isSimulated(const char* szName)
{
#if SIM_CONF == 1
(void)szName; // supress "unused parameter" warning
return true;
#else
// Your normal implementation.
#endif
}
The rest of your code doesn't need to use any macros then:
void PumpComponent::commandRevs(float revs)
{
if (SimConfig::isSimulated("PumpComponent")) {
// do simulation procedure
} else {
// do real hardware procedure
}
}
SimConfig::isReal() doesn't seem to serve any purpose.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The C preprocessor is justifiably feared and shunned by the C++ community. In-lined functions, consts and templates are usually a safer and superior alternative to a #define.
The following macro:
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
is in no way superior to the type safe:
inline bool succeeded(int hr) { return hr >= 0; }
But macros do have their place, please list the uses you find for macros that you can't do without the preprocessor.
Please put each use-cases in a seperate answer so it can be voted up and if you know of how to achieve one of the answers without the preprosessor point out how in that answer's comments.
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
Since C++20 the magic type std::source_location can however be used instead of __LINE__ and __FILE__ to implement an analogue as a normal function (template).
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:
Include guards
Conditional compilation
Reporting (predefined macros like __LINE__ and __FILE__)
(rarely) Duplicating repetitive code patterns.
In your competitor's code.
Inside conditional compilation, to overcome issues of differences between compilers:
#ifdef WE_ARE_ON_WIN32
#define close(parm1) _close (parm1)
#define rmdir(parm1) _rmdir (parm1)
#define mkdir(parm1, parm2) _mkdir (parm1)
#define access(parm1, parm2) _access(parm1, parm2)
#define create(parm1, parm2) _creat (parm1, parm2)
#define unlink(parm1) _unlink(parm1)
#endif
When you want to make a string out of an expression, the best example for this is assert (#x turns the value of x to a string).
#define ASSERT_THROW(condition) \
if (!(condition)) \
throw std::exception(#condition " is false");
String constants are sometimes better defined as macros since you can do more with string literals than with a const char *.
e.g. String literals can be easily concatenated.
#define BASE_HKEY "Software\\Microsoft\\Internet Explorer\\"
// Now we can concat with other literals
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "Settings", &settings);
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "TypedURLs", &URLs);
If a const char * were used then some sort of string class would have to be used to perform the concatenation at runtime:
const char* BaseHkey = "Software\\Microsoft\\Internet Explorer\\";
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "Settings").c_str(), &settings);
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "TypedURLs").c_str(), &URLs);
Since C++20 it is however possible to implement a string-like class type that can be used as a non-type template parameter type of a user-defined string literal operator which allows such concatenation operations at compile-time without macros.
When you want to change the program flow (return, break and continue) code in a function behaves differently than code that is actually inlined in the function.
#define ASSERT_RETURN(condition, ret_val) \
if (!(condition)) { \
assert(false && #condition); \
return ret_val; }
// should really be in a do { } while(false) but that's another discussion.
The obvious include guards
#ifndef MYHEADER_H
#define MYHEADER_H
...
#endif
Let's say we'll ignore obvious things like header guards.
Sometimes, you want to generate code that needs to be copy/pasted by the precompiler:
#define RAISE_ERROR_STL(p_strMessage) \
do \
{ \
try \
{ \
std::tstringstream strBuffer ; \
strBuffer << p_strMessage ; \
strMessage = strBuffer.str() ; \
raiseSomeAlert(__FILE__, __FUNCSIG__, __LINE__, strBuffer.str().c_str()) \
} \
catch(...){} \
{ \
} \
} \
while(false)
which enables you to code this:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
And can generate messages like:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Note that mixing templates with macros can lead to even better results (i.e. automatically generating the values side-by-side with their variable names)
Other times, you need the __FILE__ and/or the __LINE__ of some code, to generate debug info, for example. The following is a classic for Visual C++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
As with the following code:
#pragma message(WRNG "Hello World")
it generates messages like:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
Other times, you need to generate code using the # and ## concatenation operators, like generating getters and setters for a property (this is for quite a limited cases, through).
Other times, you will generate code than won't compile if used through a function, like:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Which can be used as
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(still, I only saw this kind of code rightly used once)
Last, but not least, the famous boost::foreach !!!
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
(Note: code copy/pasted from the boost homepage)
Which is (IMHO) way better than std::for_each.
So, macros are always useful because they are outside the normal compiler rules. But I find that most the time I see one, they are effectively remains of C code never translated into proper C++.
Unit test frameworks for C++ like UnitTest++ pretty much revolve around preprocessor macros. A few lines of unit test code expand into a hierarchy of classes that wouldn't be fun at all to type manually. Without something like UnitTest++ and it's preprocessor magic, I don't know how you'd efficiently write unit tests for C++.
You can't perform short-circuiting of function call arguments using a regular function call. For example:
#define andm(a, b) (a) && (b)
bool andf(bool a, bool b) { return a && b; }
andm(x, y) // short circuits the operator so if x is false, y would not be evaluated
andf(x, y) // y will always be evaluated
To fear the C preprocessor is like to fear the incandescent bulbs just because we get fluorescent bulbs. Yes, the former can be {electricity | programmer time} inefficient. Yes, you can get (literally) burned by them. But they can get the job done if you properly handle it.
When you program embedded systems, C uses to be the only option apart form assembler. After programming on desktop with C++ and then switching to smaller, embedded targets, you learn to stop worrying about “inelegancies” of so many bare C features (macros included) and just trying to figure out the best and safe usage you can get from those features.
Alexander Stepanov says:
When we program in C++ we should not be ashamed of its C heritage, but make
full use of it. The only problems with C++, and even the only problems with C, arise
when they themselves are not consistent with their own logic.
Some very advanced and useful stuff can still be built using preprocessor (macros), which you would never be able to do using the c++ "language constructs" including templates.
Examples:
Making something both a C identifier and a string
Easy way to use variables of enum types as string in C
Boost Preprocessor Metaprogramming
We use the __FILE__ and __LINE__ macros for diagnostic purposes in information rich exception throwing, catching and logging, together with automated log file scanners in our QA infrastructure.
For instance, a throwing macro OUR_OWN_THROW might be used with exception type and constructor parameters for that exception, including a textual description. Like this:
OUR_OWN_THROW(InvalidOperationException, (L"Uninitialized foo!"));
This macro will of course throw the InvalidOperationException exception with the description as constructor parameter, but it'll also write a message to a log file consisting of the file name and line number where the throw occured and its textual description. The thrown exception will get an id, which also gets logged. If the exception is ever caught somewhere else in the code, it will be marked as such and the log file will then indicate that that specific exception has been handled and that it's therefore not likely the cause of any crash that might be logged later on. Unhandled exceptions can be easily picked up by our automated QA infrastructure.
Code repetition.
Have a look to boost preprocessor library, it's a kind of meta-meta-programming. In topic->motivation you can find a good example.
One common use is for detecting the compile environment, for cross-platform development you can write one set of code for linux, say, and another for windows when no cross platform library already exists for your purposes.
So, in a rough example a cross-platform mutex can have
void lock()
{
#ifdef WIN32
EnterCriticalSection(...)
#endif
#ifdef POSIX
pthread_mutex_lock(...)
#endif
}
For functions, they are useful when you want to explicitly ignore type safety. Such as the many examples above and below for doing ASSERT. Of course, like a lot of C/C++ features you can shoot yourself in the foot, but the language gives you the tools and lets you decide what to do.
I occasionally use macros so I can define information in one place, but use it in different ways in different parts of the code. It's only slightly evil :)
For example, in "field_list.h":
/*
* List of fields, names and values.
*/
FIELD(EXAMPLE1, "first example", 10)
FIELD(EXAMPLE2, "second example", 96)
FIELD(ANOTHER, "more stuff", 32)
...
#undef FIELD
Then for a public enum it can be defined to just use the name:
#define FIELD(name, desc, value) FIELD_ ## name,
typedef field_ {
#include "field_list.h"
FIELD_MAX
} field_en;
And in a private init function, all the fields can be used to populate a table with the data:
#define FIELD(name, desc, value) \
table[FIELD_ ## name].desc = desc; \
table[FIELD_ ## name].value = value;
#include "field_list.h"
Something like
void debugAssert(bool val, const char* file, int lineNumber);
#define assert(x) debugAssert(x,__FILE__,__LINE__);
So that you can just for example have
assert(n == true);
and get the source file name and line number of the problem printed out to your log if n is false.
If you use a normal function call such as
void assert(bool val);
instead of the macro, all you can get is your assert function's line number printed to the log, which would be less useful.
#define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0])
Unlike the 'preferred' template solution discussed in a current thread, you can use it as a constant expression:
char src[23];
int dest[ARRAY_SIZE(src)];
You can use #defines to help with debugging and unit test scenarios. For example, create special logging variants of the memory functions and create a special memlog_preinclude.h:
#define malloc memlog_malloc
#define calloc memlog calloc
#define free memlog_free
Compile you code using:
gcc -Imemlog_preinclude.h ...
An link in your memlog.o to the final image. You now control malloc, etc, perhaps for logging purposes, or to simulate allocation failures for unit tests.
When you are making a decision at compile time over Compiler/OS/Hardware specific behavior.
It allows you to make your interface to Comppiler/OS/Hardware specific features.
#if defined(MY_OS1) && defined(MY_HARDWARE1)
#define MY_ACTION(a,b,c) doSothing_OS1HW1(a,b,c);}
#elif define(MY_OS1) && defined(MY_HARDWARE2)
#define MY_ACTION(a,b,c) doSomthing_OS1HW2(a,b,c);}
#elif define(MY_SUPER_OS)
/* On this hardware it is a null operation */
#define MY_ACTION(a,b,c)
#else
#error "PLEASE DEFINE MY_ACTION() for this Compiler/OS/HArdware configuration"
#endif
Compilers can refuse your request to inline.
Macros will always have their place.
Something I find useful is #define DEBUG for debug tracing -- you can leave it 1 while debugging a problem (or even leave it on during the whole development cycle) then turn it off when it is time to ship.
You can #define constants on the compiler command line using the -D or /D option. This is often useful when cross-compiling the same software for multiple platforms because you can have your makefiles control what constants are defined for each platform.
In my last job, I was working on a virus scanner. To make thing easier for me to debug, I had lots of logging stuck all over the place, but in a high demand app like that, the expense of a function call is just too expensive. So, I came up with this little Macro, that still allowed me to enable the debug logging on a release version at a customers site, without the cost of a function call would check the debug flag and just return without logging anything, or if enabled, would do the logging... The macro was defined as follows:
#define dbgmsg(_FORMAT, ...) if((debugmsg_flag & 0x00000001) || (debugmsg_flag & 0x80000000)) { log_dbgmsg(_FORMAT, __VA_ARGS__); }
Because of the VA_ARGS in the log functions, this was a good case for a macro like this.
Before that, I used a macro in a high security application that needed to tell the user that they didn't have the correct access, and it would tell them what flag they needed.
The Macro(s) defined as:
#define SECURITY_CHECK(lRequiredSecRoles) if(!DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, true)) return
#define SECURITY_CHECK_QUIET(lRequiredSecRoles) (DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, false))
Then, we could just sprinkle the checks all over the UI, and it would tell you which roles were allowed to perform the action you tried to do, if you didn't already have that role. The reason for two of them was to return a value in some places, and return from a void function in others...
SECURITY_CHECK(ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR);
LRESULT CAddPerson1::OnWizardNext()
{
if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_EMPLOYEE) {
SECURITY_CHECK(ROLE_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD ) -1;
} else if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_CONTINGENT) {
SECURITY_CHECK(ROLE_CONTINGENT_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR) -1;
}
...
Anyways, that's how I've used them, and I'm not sure how this could have been helped with templates... Other than that, I try to avoid them, unless REALLY necessary.
I use macros to easily define Exceptions:
DEF_EXCEPTION(RessourceNotFound, "Ressource not found")
where DEF_EXCEPTION is
#define DEF_EXCEPTION(A, B) class A : public exception\
{\
public:\
virtual const char* what() const throw()\
{\
return B;\
};\
}\
If you have a list of fields that get used for a bunch of things, e.g. defining a structure, serializing that structure to/from some binary format, doing database inserts, etc, then you can (recursively!) use the preprocessor to avoid ever repeating your field list.
This is admittedly hideous. But maybe sometimes better than updating a long list of fields in multiple places? I've used this technique exactly once, and it was quite helpful that one time.
Of course the same general idea is used extensively in languages with proper reflection -- just instrospect the class and operate on each field in turn. Doing it in the C preprocessor is fragile, illegible, and not always portable. So I mention it with some trepidation. Nonetheless, here it is...
(EDIT: I see now that this is similar to what #Andrew Johnson said on 9/18; however the idea of recursively including the same file takes the idea a bit further.)
// file foo.h, defines class Foo and various members on it without ever repeating the
// list of fields.
#if defined( FIELD_LIST )
// here's the actual list of fields in the class. If FIELD_LIST is defined, we're at
// the 3rd level of inclusion and somebody wants to actually use the field list. In order
// to do so, they will have defined the macros STRING and INT before including us.
STRING( fooString )
INT( barInt )
#else // defined( FIELD_LIST )
#if !defined(FOO_H)
#define FOO_H
#define DEFINE_STRUCT
// recursively include this same file to define class Foo
#include "foo.h"
#undef DEFINE_STRUCT
#define DEFINE_CLEAR
// recursively include this same file to define method Foo::clear
#include "foo.h"
#undef DEFINE_CLEAR
// etc ... many more interesting examples like serialization
#else // defined(FOO_H)
// from here on, we know that FOO_H was defined, in other words we're at the second level of
// recursive inclusion, and the file is being used to make some particular
// use of the field list, for example defining the class or a single method of it
#if defined( DEFINE_STRUCT )
#define STRING(a) std::string a;
#define INT(a) long a;
class Foo
{
public:
#define FIELD_LIST
// recursively include the same file (for the third time!) to get fields
// This is going to translate into:
// std::string fooString;
// int barInt;
#include "foo.h"
#endif
void clear();
};
#undef STRING
#undef INT
#endif // defined(DEFINE_STRUCT)
#if defined( DEFINE_ZERO )
#define STRING(a) a = "";
#define INT(a) a = 0;
#define FIELD_LIST
void Foo::clear()
{
// recursively include the same file (for the third time!) to get fields.
// This is going to translate into:
// fooString="";
// barInt=0;
#include "foo.h"
#undef STRING
#undef int
}
#endif // defined( DEFINE_ZERO )
// etc...
#endif // end else clause for defined( FOO_H )
#endif // end else clause for defined( FIELD_LIST )
I've used the preprocesser to calculate fixed-point numbers from floating point values used in embedded systems that cannot use floating point in the compiled code. It's handy to have all of your math in Real World Units and not have to think about them in fixed-point.
Example:
// TICKS_PER_UNIT is defined in floating point to allow the conversions to compute during compile-time.
#define TICKS_PER_UNIT 1024.0
// NOTE: The TICKS_PER_x_MS will produce constants in the preprocessor. The (long) cast will
// guarantee there are no floating point values in the embedded code and will produce a warning
// if the constant is larger than the data type being stored to.
// Adding 0.5 sec to the calculation forces rounding instead of truncation.
#define TICKS_PER_1_MS( ms ) (long)( ( ( ms * TICKS_PER_UNIT ) / 1000 ) + 0.5 )
Yet another foreach macros. T: type, c: container, i: iterator
#define foreach(T, c, i) for(T::iterator i=(c).begin(); i!=(c).end(); ++i)
#define foreach_const(T, c, i) for(T::const_iterator i=(c).begin(); i!=(c).end(); ++i)
Usage (concept showing, not real):
void MultiplyEveryElementInList(std::list<int>& ints, int mul)
{
foreach(std::list<int>, ints, i)
(*i) *= mul;
}
int GetSumOfList(const std::list<int>& ints)
{
int ret = 0;
foreach_const(std::list<int>, ints, i)
ret += *i;
return ret;
}
Better implementations available: Google "BOOST_FOREACH"
Good articles available: Conditional Love: FOREACH Redux (Eric Niebler) http://www.artima.com/cppsource/foreach.html
Maybe the greates usage of macros is in platform-independent development.
Think about cases of type inconsistency - with macros, you can simply use different header files -- like:
--WIN_TYPES.H
typedef ...some struct
--POSIX_TYPES.h
typedef ...some another struct
--program.h
#ifdef WIN32
#define TYPES_H "WINTYPES.H"
#else
#define TYPES_H "POSIX_TYPES.H"
#endif
#include TYPES_H
Much readable than implementing it in other ways, to my opinion.
I've a very basic class, name it Basic, used in nearly all other files in a bigger project. In some cases, there needs to be debug output, but in release mode, this should not be enabled and be a NOOP.
Currently there is a define in the header, which switches a makro on or off, depending on the setting. So this is definetely a NOOP, when switched off. I'm wondering, if I have the following code, if a compiler (MSVS / gcc) is able to optimize out the function call, so that it is again a NOOP. (By doing that, the switch could be in the .cpp and switching will be much faster, compile/link time wise).
--Header--
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
printDebug(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
As with all questions like this, the answer is - if it really matters to you, try the approach and examine the emitted assembly language.
Compiler possibly may optimize this code, if it knows printDebug function implementation at compilation time. If printDebug is in another object module, this possibly may be optimized only by linker, using the whole program optimization. But the only way to test this is to read compiler-generated Assembly code.
If you already have PRINT_DEBUG macro, you can extend it by the way as TRACE is defined:
#define PRINT_DEBUG // optional
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#else
#define PRINT_DEBUG_CALL(p)
#endif
void printDebug(const Basic* p);
class Basic {
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
PRINT_DEBUG_CALL(this);
}
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
// Lengthy debug print
}
#endif
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif
This way the preprocessor will strip all debug code before it even gets to the compiler.
Currently most of the optimizations are done at compile time. Some compilers as LLVM are able to optimize at link time. This is a really interesting idea. I suggest you to take a look at.
Waiting for these kind of optimization, what you can do is the following. Define a macro that let you include the following statement depending on whether DEBUG is defined or not.
#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG
#endif
You can the use it like this
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
IF_DEBUG printDebug(this);
}
which is already much more readable than
Basic() {
simpleSetupCode;
// this should be a NOOP in release,
// but constructor could be inlined
#if DEBUG
printDebug(this);
#endif
}
Note that you can use it as if it was a keyword
IF_DEBUG {
printDebug(this);
printDebug(thas);
}
errm, why not use the pre-processor macro differently?
Just of the top of my head, something like:
#define DEBUG_TRACE(p)
#ifdef PRINT_DEBUG
printDebug(p);
#else
;
#endif
Is it possible to do something like this
#ifdef SOMETHING
#define foo //
#else
#define foo MyFunction
#endif
The idea is that if SOMETHING is defined, then calls to foo(...) become comments (or something that doesn't get evaluated or compiled), otherwise it becomes a call to MyFunction.
I've seen __noop used, but I don't believe I can use that.
EDIT(s):
I don't think I can really use a macro here, because MyFunction takes a variable number of arguments.
Also, I'd like to make it so the arguments are NOT evaluated! (So doing something like commenting out the body of MyFunction doesn't really give me what I need, as the arguments will still be evaluated)
Try this:
#ifdef SOMETHING
#define foo(x)
#else
#define foo(x) MyFunction(x)
#endif
If your function has several arguments, then:
#ifdef SOMETHING
#define foo(x,y,z)
#else
#define foo(x,y,z) MyFunction(x,y,z)
#endif
If your function has a variable number of arguments, then your compiler may support so-called "variadic macros", like this:
#ifdef SOMETHING
#define foo(...)
#else
#define foo(...) MyFunction(__VA_ARGS__)
#endif
The reason which I've seen this kind of thing used in practice is to get rid of logging functions from a release build. However, see also Separate 'debug' and 'release' builds? in which people question whether you should even have different builds.
Alternatively, instead of redefining the function call as nothing, Jonathan's comment to this answer suggested doing something like the following:
#ifdef SOMETHING
#define foo(...) do { if (false) MyFunction(__VA_ARGS__) } while (0)
#else
#define foo(...) do { if (true) MyFunction(__VA_ARGS__) } while (0)
#endif
The reasoning for doing this is so that the function call is always compiled (so it won't be left with gratuitous errors like references to deleted variables), but only called when needed: see Kernighan & Pike The Practice of Programming and also the Goddard Space Flight Center programming standards.
From a debug.h file (originating from 1990, and therefore not using __VA_ARGS__):
/*
** Usage: TRACE((level, fmt, ...))
** "level" is the debugging level which must be operational for the output
** to appear. "fmt" is a printf format string. "..." is whatever extra
** arguments fmt requires (possibly nothing).
** The non-debug macro means that the code is validated but never called.
** -- See chapter 8 of 'The Practice of Programming', by Kernighan and Pike.
*/
#ifdef DEBUG
#define TRACE(x) db_print x
#else
#define TRACE(x) do { if (0) db_print x; } while (0)
#endif /* DEBUG */
With C99, there's no longer a need for the double parentheses trick. New code should not use it unless C89 compatibility is an issue.
Maybe an easier way to do this would be to conditionally omit the body of the function?
void MyFunction() {
#ifndef SOMETHING
<body of function>
#endif
}
Unless you specifically don't want a function call to be made at all, this seems like a clean way to achieve your goal.
Unfortunately the current C++ version doesn't support variadic macros.
However, you can do this:
#ifdef SOMETHING
#define foo
#else
#define foo(args) MyFunction args
#endif
// you call it with double parens:
foo((a, b, c));
If, in the case you don't want foo called, you define it as:
void foo() {}
any calls to foo() should be optimized way.
What about something along these lines:
#ifdef NDEBUG
#define DEBUG(STATEMENT) ((void)0)
#else
#define DEBUG(STATEMENT) (STATEMENT)
#endif
You would use it like this to log debugging messages:
DEBUG(puts("compile with -DNDEBUG and I'm gone"));
A non-generic version for formatted output with additional debugging information using C99 variadic macros and the __func__ identifier could look like this:
#ifdef NDEBUG
#define Dprintf(FORMAT, ...) ((void)0)
#define Dputs(MSG) ((void)0)
#else
#define Dprintf(FORMAT, ...) \
fprintf(stderr, "%s() in %s, line %i: " FORMAT "\n", \
__func__, __FILE__, __LINE__, __VA_ARGS__)
#define Dputs(MSG) Dprintf("%s", MSG)
#endif
Here's how you'd use these macros:
Dprintf("count = %i", count);
Dputs("checkpoint passed");
Likely, you don't want to do the simple "code removal" as suggested,
because your callers will be expecting the side effects of the
arguments to happen. Here are some troublesome caller snippets that
should get you thinking:
// pre/post increment inside method call:
MyFunction(i++);
// Function call (with side effects) used as method argument:
MyFunction( StoreNewUsernameIntoDatabase(username) );
If you were to disable MyFunction by simply saying:
#define MyFunction(x)
then the side effects that the callers were expecting would go away,
and their code would break, and be quite difficult to debug. I like
the "sizeof" suggestion above, and I also like the suggestion to just
disable the body of MyFunction() via #ifdef's, although that means
that all callers get the same version of MyFunction(). From your
problem statement, I presume that's not actually what you want.
If you really need to disable MyFunction() via preprocessor defines on
a per-source-file basis, then I'd do it like this:
#ifdef SOMETHING
#define MyFunction(x) NoOp_MyFunction(x)
int NoOp_MyFunction(x) { }
#endif
You could even include the implementation of NoOp_MyFunction() inside
the source & headers for MyFunction(). You also have the flexibility
to add extra logging or debugging information in NoOp_MyFunction() as
well.
No, the C and C++ Standards say you cannot #define something to be a comment, so
#define foo //
won't work.
#ifdef SOMETHING
#define foo sizeof
#else
#define foo MyFunction
#endif
I'm assuming that foo is a printf style function? Anyways, this won't work with a zero parameter function, but if that were the case, you would already know what to do. If you really want to be anal you can use (void)sizeof but that's probably unnecessary.
I'm a little reluctant to post this answer because it's use of macro hackery can become the source of problems. However - if the calls to the function you want to have disappear are always used alone in a statement (ie., they are never part of a larger expression), then something like the following could work (and it handles varargs):
#ifdef SOMETHING
#define foo (1) ? ((void) 0) : (void)
#else
#define foo MyFunction
#endif
So if you have the line of code:
foo( "this is a %s - a++ is %d\n", "test", a++);
it will end up after the preprocessing step as either:
MyFunction( "this is a %s - a++ is %d\n", "test", a++);
or
(1) ? ((void) 0) : (void)( "this is a %s - a++ is %d\n", "test", a++);
which turns the pseudo-function's parameter list into a bunch of expressions separated by the comma operator that will never be evaluated, since the conditional always returns the ((void) 0) result.
A variant of this is something close to what ChriSW and Jonathan Leffler suggested:
#ifdef SOMETHING
#define foo if (0) MyFunction
#else
#define foo if (1) MyFunction
#endif
This is slightly different in that it does not require the compiler to support variadic macros (__VA_ARGS__).
I think this can be useful for eliminating debug trace function calls which are generally never combined into a larger expression, but beyond that I think it's a dangerous technique.
Note the potential for problems - especially if the parameters in the call produce side-effects (this is a general problem with macros - not just this hack). In the example, the a++ will be evaluated only if SOMETHING is defined in the build, otherwise it's not. So if code after the call depends on the value of a to be incremented, one of the builds has a bug.
If I remember correctly, you should be able to #define your macro to "nothing" and that will cause the compiler to ignore that call
#define foo()
foo(); // this will be ignored
What about surrounding each call to myFunction with
#ifdef SOMETHING
myFunction(...);
#endif
?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The C preprocessor is justifiably feared and shunned by the C++ community. In-lined functions, consts and templates are usually a safer and superior alternative to a #define.
The following macro:
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
is in no way superior to the type safe:
inline bool succeeded(int hr) { return hr >= 0; }
But macros do have their place, please list the uses you find for macros that you can't do without the preprocessor.
Please put each use-cases in a seperate answer so it can be voted up and if you know of how to achieve one of the answers without the preprosessor point out how in that answer's comments.
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
Since C++20 the magic type std::source_location can however be used instead of __LINE__ and __FILE__ to implement an analogue as a normal function (template).
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:
Include guards
Conditional compilation
Reporting (predefined macros like __LINE__ and __FILE__)
(rarely) Duplicating repetitive code patterns.
In your competitor's code.
Inside conditional compilation, to overcome issues of differences between compilers:
#ifdef WE_ARE_ON_WIN32
#define close(parm1) _close (parm1)
#define rmdir(parm1) _rmdir (parm1)
#define mkdir(parm1, parm2) _mkdir (parm1)
#define access(parm1, parm2) _access(parm1, parm2)
#define create(parm1, parm2) _creat (parm1, parm2)
#define unlink(parm1) _unlink(parm1)
#endif
When you want to make a string out of an expression, the best example for this is assert (#x turns the value of x to a string).
#define ASSERT_THROW(condition) \
if (!(condition)) \
throw std::exception(#condition " is false");
String constants are sometimes better defined as macros since you can do more with string literals than with a const char *.
e.g. String literals can be easily concatenated.
#define BASE_HKEY "Software\\Microsoft\\Internet Explorer\\"
// Now we can concat with other literals
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "Settings", &settings);
RegOpenKey(HKEY_CURRENT_USER, BASE_HKEY "TypedURLs", &URLs);
If a const char * were used then some sort of string class would have to be used to perform the concatenation at runtime:
const char* BaseHkey = "Software\\Microsoft\\Internet Explorer\\";
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "Settings").c_str(), &settings);
RegOpenKey(HKEY_CURRENT_USER, (string(BaseHkey) + "TypedURLs").c_str(), &URLs);
Since C++20 it is however possible to implement a string-like class type that can be used as a non-type template parameter type of a user-defined string literal operator which allows such concatenation operations at compile-time without macros.
When you want to change the program flow (return, break and continue) code in a function behaves differently than code that is actually inlined in the function.
#define ASSERT_RETURN(condition, ret_val) \
if (!(condition)) { \
assert(false && #condition); \
return ret_val; }
// should really be in a do { } while(false) but that's another discussion.
The obvious include guards
#ifndef MYHEADER_H
#define MYHEADER_H
...
#endif
Let's say we'll ignore obvious things like header guards.
Sometimes, you want to generate code that needs to be copy/pasted by the precompiler:
#define RAISE_ERROR_STL(p_strMessage) \
do \
{ \
try \
{ \
std::tstringstream strBuffer ; \
strBuffer << p_strMessage ; \
strMessage = strBuffer.str() ; \
raiseSomeAlert(__FILE__, __FUNCSIG__, __LINE__, strBuffer.str().c_str()) \
} \
catch(...){} \
{ \
} \
} \
while(false)
which enables you to code this:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
And can generate messages like:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
Note that mixing templates with macros can lead to even better results (i.e. automatically generating the values side-by-side with their variable names)
Other times, you need the __FILE__ and/or the __LINE__ of some code, to generate debug info, for example. The following is a classic for Visual C++:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
As with the following code:
#pragma message(WRNG "Hello World")
it generates messages like:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
Other times, you need to generate code using the # and ## concatenation operators, like generating getters and setters for a property (this is for quite a limited cases, through).
Other times, you will generate code than won't compile if used through a function, like:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
Which can be used as
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(still, I only saw this kind of code rightly used once)
Last, but not least, the famous boost::foreach !!!
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
(Note: code copy/pasted from the boost homepage)
Which is (IMHO) way better than std::for_each.
So, macros are always useful because they are outside the normal compiler rules. But I find that most the time I see one, they are effectively remains of C code never translated into proper C++.
Unit test frameworks for C++ like UnitTest++ pretty much revolve around preprocessor macros. A few lines of unit test code expand into a hierarchy of classes that wouldn't be fun at all to type manually. Without something like UnitTest++ and it's preprocessor magic, I don't know how you'd efficiently write unit tests for C++.
You can't perform short-circuiting of function call arguments using a regular function call. For example:
#define andm(a, b) (a) && (b)
bool andf(bool a, bool b) { return a && b; }
andm(x, y) // short circuits the operator so if x is false, y would not be evaluated
andf(x, y) // y will always be evaluated
To fear the C preprocessor is like to fear the incandescent bulbs just because we get fluorescent bulbs. Yes, the former can be {electricity | programmer time} inefficient. Yes, you can get (literally) burned by them. But they can get the job done if you properly handle it.
When you program embedded systems, C uses to be the only option apart form assembler. After programming on desktop with C++ and then switching to smaller, embedded targets, you learn to stop worrying about “inelegancies” of so many bare C features (macros included) and just trying to figure out the best and safe usage you can get from those features.
Alexander Stepanov says:
When we program in C++ we should not be ashamed of its C heritage, but make
full use of it. The only problems with C++, and even the only problems with C, arise
when they themselves are not consistent with their own logic.
Some very advanced and useful stuff can still be built using preprocessor (macros), which you would never be able to do using the c++ "language constructs" including templates.
Examples:
Making something both a C identifier and a string
Easy way to use variables of enum types as string in C
Boost Preprocessor Metaprogramming
We use the __FILE__ and __LINE__ macros for diagnostic purposes in information rich exception throwing, catching and logging, together with automated log file scanners in our QA infrastructure.
For instance, a throwing macro OUR_OWN_THROW might be used with exception type and constructor parameters for that exception, including a textual description. Like this:
OUR_OWN_THROW(InvalidOperationException, (L"Uninitialized foo!"));
This macro will of course throw the InvalidOperationException exception with the description as constructor parameter, but it'll also write a message to a log file consisting of the file name and line number where the throw occured and its textual description. The thrown exception will get an id, which also gets logged. If the exception is ever caught somewhere else in the code, it will be marked as such and the log file will then indicate that that specific exception has been handled and that it's therefore not likely the cause of any crash that might be logged later on. Unhandled exceptions can be easily picked up by our automated QA infrastructure.
Code repetition.
Have a look to boost preprocessor library, it's a kind of meta-meta-programming. In topic->motivation you can find a good example.
One common use is for detecting the compile environment, for cross-platform development you can write one set of code for linux, say, and another for windows when no cross platform library already exists for your purposes.
So, in a rough example a cross-platform mutex can have
void lock()
{
#ifdef WIN32
EnterCriticalSection(...)
#endif
#ifdef POSIX
pthread_mutex_lock(...)
#endif
}
For functions, they are useful when you want to explicitly ignore type safety. Such as the many examples above and below for doing ASSERT. Of course, like a lot of C/C++ features you can shoot yourself in the foot, but the language gives you the tools and lets you decide what to do.
I occasionally use macros so I can define information in one place, but use it in different ways in different parts of the code. It's only slightly evil :)
For example, in "field_list.h":
/*
* List of fields, names and values.
*/
FIELD(EXAMPLE1, "first example", 10)
FIELD(EXAMPLE2, "second example", 96)
FIELD(ANOTHER, "more stuff", 32)
...
#undef FIELD
Then for a public enum it can be defined to just use the name:
#define FIELD(name, desc, value) FIELD_ ## name,
typedef field_ {
#include "field_list.h"
FIELD_MAX
} field_en;
And in a private init function, all the fields can be used to populate a table with the data:
#define FIELD(name, desc, value) \
table[FIELD_ ## name].desc = desc; \
table[FIELD_ ## name].value = value;
#include "field_list.h"
Something like
void debugAssert(bool val, const char* file, int lineNumber);
#define assert(x) debugAssert(x,__FILE__,__LINE__);
So that you can just for example have
assert(n == true);
and get the source file name and line number of the problem printed out to your log if n is false.
If you use a normal function call such as
void assert(bool val);
instead of the macro, all you can get is your assert function's line number printed to the log, which would be less useful.
#define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0])
Unlike the 'preferred' template solution discussed in a current thread, you can use it as a constant expression:
char src[23];
int dest[ARRAY_SIZE(src)];
You can use #defines to help with debugging and unit test scenarios. For example, create special logging variants of the memory functions and create a special memlog_preinclude.h:
#define malloc memlog_malloc
#define calloc memlog calloc
#define free memlog_free
Compile you code using:
gcc -Imemlog_preinclude.h ...
An link in your memlog.o to the final image. You now control malloc, etc, perhaps for logging purposes, or to simulate allocation failures for unit tests.
When you are making a decision at compile time over Compiler/OS/Hardware specific behavior.
It allows you to make your interface to Comppiler/OS/Hardware specific features.
#if defined(MY_OS1) && defined(MY_HARDWARE1)
#define MY_ACTION(a,b,c) doSothing_OS1HW1(a,b,c);}
#elif define(MY_OS1) && defined(MY_HARDWARE2)
#define MY_ACTION(a,b,c) doSomthing_OS1HW2(a,b,c);}
#elif define(MY_SUPER_OS)
/* On this hardware it is a null operation */
#define MY_ACTION(a,b,c)
#else
#error "PLEASE DEFINE MY_ACTION() for this Compiler/OS/HArdware configuration"
#endif
Compilers can refuse your request to inline.
Macros will always have their place.
Something I find useful is #define DEBUG for debug tracing -- you can leave it 1 while debugging a problem (or even leave it on during the whole development cycle) then turn it off when it is time to ship.
You can #define constants on the compiler command line using the -D or /D option. This is often useful when cross-compiling the same software for multiple platforms because you can have your makefiles control what constants are defined for each platform.
In my last job, I was working on a virus scanner. To make thing easier for me to debug, I had lots of logging stuck all over the place, but in a high demand app like that, the expense of a function call is just too expensive. So, I came up with this little Macro, that still allowed me to enable the debug logging on a release version at a customers site, without the cost of a function call would check the debug flag and just return without logging anything, or if enabled, would do the logging... The macro was defined as follows:
#define dbgmsg(_FORMAT, ...) if((debugmsg_flag & 0x00000001) || (debugmsg_flag & 0x80000000)) { log_dbgmsg(_FORMAT, __VA_ARGS__); }
Because of the VA_ARGS in the log functions, this was a good case for a macro like this.
Before that, I used a macro in a high security application that needed to tell the user that they didn't have the correct access, and it would tell them what flag they needed.
The Macro(s) defined as:
#define SECURITY_CHECK(lRequiredSecRoles) if(!DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, true)) return
#define SECURITY_CHECK_QUIET(lRequiredSecRoles) (DoSecurityCheck(lRequiredSecRoles, #lRequiredSecRoles, false))
Then, we could just sprinkle the checks all over the UI, and it would tell you which roles were allowed to perform the action you tried to do, if you didn't already have that role. The reason for two of them was to return a value in some places, and return from a void function in others...
SECURITY_CHECK(ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR);
LRESULT CAddPerson1::OnWizardNext()
{
if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_EMPLOYEE) {
SECURITY_CHECK(ROLE_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD ) -1;
} else if(m_Role.GetItemData(m_Role.GetCurSel()) == parent->ROLE_CONTINGENT) {
SECURITY_CHECK(ROLE_CONTINGENT_WORKER_ADMINISTRATOR | ROLE_BUSINESS_INFORMATION_STEWARD | ROLE_WORKER_ADMINISTRATOR) -1;
}
...
Anyways, that's how I've used them, and I'm not sure how this could have been helped with templates... Other than that, I try to avoid them, unless REALLY necessary.
I use macros to easily define Exceptions:
DEF_EXCEPTION(RessourceNotFound, "Ressource not found")
where DEF_EXCEPTION is
#define DEF_EXCEPTION(A, B) class A : public exception\
{\
public:\
virtual const char* what() const throw()\
{\
return B;\
};\
}\
If you have a list of fields that get used for a bunch of things, e.g. defining a structure, serializing that structure to/from some binary format, doing database inserts, etc, then you can (recursively!) use the preprocessor to avoid ever repeating your field list.
This is admittedly hideous. But maybe sometimes better than updating a long list of fields in multiple places? I've used this technique exactly once, and it was quite helpful that one time.
Of course the same general idea is used extensively in languages with proper reflection -- just instrospect the class and operate on each field in turn. Doing it in the C preprocessor is fragile, illegible, and not always portable. So I mention it with some trepidation. Nonetheless, here it is...
(EDIT: I see now that this is similar to what #Andrew Johnson said on 9/18; however the idea of recursively including the same file takes the idea a bit further.)
// file foo.h, defines class Foo and various members on it without ever repeating the
// list of fields.
#if defined( FIELD_LIST )
// here's the actual list of fields in the class. If FIELD_LIST is defined, we're at
// the 3rd level of inclusion and somebody wants to actually use the field list. In order
// to do so, they will have defined the macros STRING and INT before including us.
STRING( fooString )
INT( barInt )
#else // defined( FIELD_LIST )
#if !defined(FOO_H)
#define FOO_H
#define DEFINE_STRUCT
// recursively include this same file to define class Foo
#include "foo.h"
#undef DEFINE_STRUCT
#define DEFINE_CLEAR
// recursively include this same file to define method Foo::clear
#include "foo.h"
#undef DEFINE_CLEAR
// etc ... many more interesting examples like serialization
#else // defined(FOO_H)
// from here on, we know that FOO_H was defined, in other words we're at the second level of
// recursive inclusion, and the file is being used to make some particular
// use of the field list, for example defining the class or a single method of it
#if defined( DEFINE_STRUCT )
#define STRING(a) std::string a;
#define INT(a) long a;
class Foo
{
public:
#define FIELD_LIST
// recursively include the same file (for the third time!) to get fields
// This is going to translate into:
// std::string fooString;
// int barInt;
#include "foo.h"
#endif
void clear();
};
#undef STRING
#undef INT
#endif // defined(DEFINE_STRUCT)
#if defined( DEFINE_ZERO )
#define STRING(a) a = "";
#define INT(a) a = 0;
#define FIELD_LIST
void Foo::clear()
{
// recursively include the same file (for the third time!) to get fields.
// This is going to translate into:
// fooString="";
// barInt=0;
#include "foo.h"
#undef STRING
#undef int
}
#endif // defined( DEFINE_ZERO )
// etc...
#endif // end else clause for defined( FOO_H )
#endif // end else clause for defined( FIELD_LIST )
I've used the preprocesser to calculate fixed-point numbers from floating point values used in embedded systems that cannot use floating point in the compiled code. It's handy to have all of your math in Real World Units and not have to think about them in fixed-point.
Example:
// TICKS_PER_UNIT is defined in floating point to allow the conversions to compute during compile-time.
#define TICKS_PER_UNIT 1024.0
// NOTE: The TICKS_PER_x_MS will produce constants in the preprocessor. The (long) cast will
// guarantee there are no floating point values in the embedded code and will produce a warning
// if the constant is larger than the data type being stored to.
// Adding 0.5 sec to the calculation forces rounding instead of truncation.
#define TICKS_PER_1_MS( ms ) (long)( ( ( ms * TICKS_PER_UNIT ) / 1000 ) + 0.5 )
Yet another foreach macros. T: type, c: container, i: iterator
#define foreach(T, c, i) for(T::iterator i=(c).begin(); i!=(c).end(); ++i)
#define foreach_const(T, c, i) for(T::const_iterator i=(c).begin(); i!=(c).end(); ++i)
Usage (concept showing, not real):
void MultiplyEveryElementInList(std::list<int>& ints, int mul)
{
foreach(std::list<int>, ints, i)
(*i) *= mul;
}
int GetSumOfList(const std::list<int>& ints)
{
int ret = 0;
foreach_const(std::list<int>, ints, i)
ret += *i;
return ret;
}
Better implementations available: Google "BOOST_FOREACH"
Good articles available: Conditional Love: FOREACH Redux (Eric Niebler) http://www.artima.com/cppsource/foreach.html
Maybe the greates usage of macros is in platform-independent development.
Think about cases of type inconsistency - with macros, you can simply use different header files -- like:
--WIN_TYPES.H
typedef ...some struct
--POSIX_TYPES.h
typedef ...some another struct
--program.h
#ifdef WIN32
#define TYPES_H "WINTYPES.H"
#else
#define TYPES_H "POSIX_TYPES.H"
#endif
#include TYPES_H
Much readable than implementing it in other ways, to my opinion.