Related
I've implemented a log function, that eventually is being used identically all over the code.
void func(int foo, int bar){
log_api_call("foo", foo, "bar",bar)
...
}
so I've decided to make it easier and just extract the variable names.
so it would be something like
log_api_call(foo,bar)
or even better
log_api_call()
and it would expand to log_api_call("foo", foo, "bar",bar) somehow.
I have no idea even where to start to 'extract' the function variable names.
help would be much appreciated.
Edit:
I understand that what I've asked previously is outside of the C++ preprocessor capabilities, but can C MACROS expand log_api(a,b) to log_api_call("a", a, "b", b) for any number of parameters?
for defined number the job is trivial.
Thanks.
This isn't actually too difficult.
I'd recommend a slight change in spec though; instead of:
expand log_api(a,b) to log_api_call("a", a, "b", b)
...it's more useful to expand something like NAMED_VALUES(a,b) to "a",a,"b",b. You can then call log_api(NAMED_VALUES(a,b)), but your log_api can stay more generic (e.g., log_api(NAMED_VALUES(a,b),"entering function") is possible). This approach also avoids a lot of complications about zero-argument cases.
// A preprocessor argument counter
#define COUNT(...) COUNT_I(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1,)
#define COUNT_I(_9,_8,_7,_6,_5,_4,_3,_2,_1,X,...) X
// Preprocessor paster
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
// chained caller
#define NAMED_VALUES(...) GLUE(NAMED_VALUES_,COUNT(__VA_ARGS__))(__VA_ARGS__)
// chain
#define NAMED_VALUES_1(a) #a,a
#define NAMED_VALUES_2(a,...) #a,a,NAMED_VALUES_1(__VA_ARGS__)
#define NAMED_VALUES_3(a,...) #a,a,NAMED_VALUES_2(__VA_ARGS__)
#define NAMED_VALUES_4(a,...) #a,a,NAMED_VALUES_3(__VA_ARGS__)
#define NAMED_VALUES_5(a,...) #a,a,NAMED_VALUES_4(__VA_ARGS__)
#define NAMED_VALUES_6(a,...) #a,a,NAMED_VALUES_5(__VA_ARGS__)
#define NAMED_VALUES_7(a,...) #a,a,NAMED_VALUES_6(__VA_ARGS__)
#define NAMED_VALUES_8(a,...) #a,a,NAMED_VALUES_7(__VA_ARGS__)
#define NAMED_VALUES_9(a,...) #a,a,NAMED_VALUES_8(__VA_ARGS__)
This supports up to 9 arguments, but it should be easy to see how to expand to more.
This is not possible in standard C++11 (or standard C11 - which nearly shares its preprocessor with C++). The C or C++ preprocessor don't know the AST of your code passed to the compiler (because it is running before the actual parsing of your code).
I have no idea even where to start to 'extract' the function variable names.
Notice that variable and function names are known only at compilation time (after preprocessing). So if you want them, you need to work during compilation. At execution time variables and functions names are generally lost (and you could strip your executable).
You could generate your C++ code (e.g.using some other preprocessor like GPP or M4, or writing your own thing).
You could customize your C++ compiler (e.g. with an extension in GCC MELT, or a GCC plugin) to e.g. have log_api_call invoke some new magic builtin (whose processing inside the compiler would do most of the job). This would take months and is very compiler specific, I don't think it is worth the pain.
You could parse DWARF debugging info (that would also take months, so I don't think it would be wise).
(I am implicitly thinking of C++ code compiled on a Linux system)
Read more about aspect programming.
If you want such powerful meta-programming facilities, C++ is the wrong programming language. Read more about the powerful macro system of Common Lisp...
but can C MACROS expand log_api(a,b) to log_api_call("a", a, "b", b) for any number of parameters? for defined number the job is trivial.
No. You need a more powerful preprocessor to do that job (or write your own). For that specific need, you might consider customizing your source code editor (e.g. write a hundred lines of ELisp code doing that extraction & expansion job at edit time for emacs).
PS In practice you could find some library (probably boost) limiting the arguments to some reasonable limit
I think the best you can achieve from inside the language is writing a macro LOG_API_CALL(foo,bar) that expands to log_api_call("foo", foo, "bar", bar):
#define LOG_API_CALL(P1,P2) log_api_call(#P1,P1,#P2,P1)
This gets pretty tricky if you want to support arbitrarily many arguments with a single macro name, but you could also have a separate macro for each number of arguments.
and it would expand to log_api_call("foo", foo, "bar",bar) somehow.
This is not possible in Standard C++.
Hello all I was having trouble with macros so I thought I would practice and I was looking at the ## macro operator and thought I could use it for my problem I wan't to be able to call multiple functions based on the parameter for example if I have a macro like so:
#define macro(a) func##a();
int main()
{
.....
for(int i = 0;i< length;i++)
{
macro(i)
}
func1()
{
}
....
func31()
{
}
Anyone have an idea of how I can accomplish this??
You can only combine two preprocessor tokens. However, func isn't a preprocessor token. You need to jump through an extra hoop, calling some form of "concat" macro:
#define CONCAT(a, b) a ## b
#define macro(a) CONCAT(func,a)
Of course, the tokens produced by you macro won't be func1, ..., func31 (of course, they would also need to start with func0 if your logic were correct) but rather funci. The expansion of macros happens at the beginning of compilation while the execution of the for-loop happens at run-time (some optimizations may hoist it into compile-time but that won't affect the macros).
If you need to expand a sequence of integers in combination with a macro, you may want to have a look at the Boost preprocessor library, in particular at the BOOST_PP_REPEAT functionality.
If you just need to statically expand a sequence of integers to function calls, you might also consider looking at function template templatized on an integers: I would certainly consider using an approach using templates before trying to use the preprocessor library...
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 9 years ago.
Improve this question
As far as I know, macros rearrange the program text before the compiler even sees it properly, thus potentially causing problems. I hardly ever see them in C++ code, mostly in C.
The only good use I know of, is inclusion guards (#ifndef).
Is there anything else that needs to be done with macros and cannot be implemented in a cleaner way?
Logging and Exception.
A macro allows you to effortlessly capture __FILE__, __LINE__ and __func__. Oh sure you could write them manually each time, but frankly this is tedious and error prone (both __FILE__ and __func__ are C-string so you risk mixing them up).
Prior to C++11, you would usually define static_assert as a macro (a typedef that would be invalid if the condition is false), so it can be available from anywhere (namespace level, or function level) and still not be ambiguous (e.g. by using a line number).
The Boost.Preprocessor library is another good example of using macros to reduce the amount of highly redundant code, and another one that is less relevant with variadic templates.
Furthermore macros are widely used to "talk" to the compiler, e.g. checking what compiler you are running on, what version of the compiler, whether C++11 support is available, etc.
Yes, the X-macro trick will always be useful.
You put your data in one header (no #include guards!), then use a macro to conditionally expand it.
Example:
Data.h:
X(Option1, "Description of option 1", int, long)
X(Option2, "Description of option 2", double, short)
X(Option3, "Description of option 3", wchar_t*, char *)
MyProgram.cpp:
enum Options
{
#define X(Option, Description, Arg1, Arg2) Option,
# include "Data.h"
#undef X
};
char const *descriptions[] =
{
#define X(Option, Description, Arg1, Arg2) Description,
# include "Data.h"
#undef X
};
#define X(Option, Description, Arg1, Arg2) typedef void (*P##Option)(Arg1, Arg2);
# include "Data.h"
#undef X
It's not the prettiest sight, but it avoids code duplication and lets you keep everything in one place.
Macros can be defined from the compiler command line, with -DFOO, which would define the macro FOO. This is most often used for conditional compilation, e.g. a certain optimization that is known to work on some platforms but not on others. The build system can detect whether the optimization is viable an enable it using this kind of macro.
This is one of the few uses of macros that I believe can be used well. However, it's of course possible to abuse this feature as well.
The macros are considered error prone due to its characteristics, here we have some good examples of error prone macros:
Macros VS inline functions.
Macros containing if.
Multiple line macros.
Concatenation macros.
But they could be useful in some ways, for example, in order to make te code more readable when dealing with function pointers:
class Fred {
public:
int f(char x, float y);
int g(char x, float y);
int h(char x, float y);
int i(char x, float y);
// ...
};
// FredMemberFn points to a member of Fred that takes (char,float)
typedef int (Fred::*FredMemberFn)(char x, float y);
// Useful macro:
#define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember))
With the "Useful macro", you can call function pointers like this:
callMemberFunction(fred,memFn)('x', 3.14);
That is slightly more clear than:
(fred.*memFn)('x', 3.14);
Credits: C++ FAQ Lite.
Several uses (some may have been mentioned already..)
Logging: DEBUG(....), this is neat because the contents are only evaluated if the logging is active (so the macro could have a test for log level for example...) You cannot replace this with an inline function as the arguments will always be evaluated. However with c++11, there is a lambda trick which will avoid the evaluation, however the syntnax is cludgy so you'll end requiring a macro anyway to clean it up! :)
Code generation, I use lots of SFINAE tests, and it's easy to generate the test with a couple of macros rather than hand construct the test every time.
There are some code rewriting for optimization that seem not to be doable with template metaprogramming and need macros. Here is a probable example: C++ template for unrolling a loop using a switch?
Yes, they will still have uses such as for "message maps" in ATL, WTL, MFC.
For example, this is part of some personal code I have:
BEGIN_MSG_MAP(This)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
COMMAND_RANGE_HANDLER(IDOK, IDNO, OnButtonClick)
CHAIN_MSG_MAP(CDialogResize<This>)
END_MSG_MAP()
Or even specifying the layout of a window:
BEGIN_DLGRESIZE_MAP(This)
DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_EDITINPUT, DLSZ_SIZE_X)
END_DLGRESIZE_MAP()
Writing this without macros would involve a lot of unnecessary boilerplate code.
When you need to utilize platform, compiler, or implementation specific features. Typically, this is either to improve portability or to access features which are expressed differently in the systems you target (i.e. it may be written differently on the compilers you use).
And expanding on Matthieu's answer (+1): Assertions.
Writing exception-checking tests with macros is much easier than with functions.
#define TEST_THROWS(code) do { try { code; } catch (...) { pass(); } fail(); } while(0)
Note: example not tested
Extending on the answer from #Matthieu, I've used macros to add file and line logging to a legacy codebase. So this:
void MovePlayer(Vector3 position)
{
...
}
became something like:
#define MovePlayer(pos) MovePlayer_(pos, __FILE__, __LINE__)
void MovePlayer_(Vector3 position, const char* file, int line)
{
LogFunctionCall("MovePlayer", file, line);
...
}
By only changing one place in the codebase, I was able to log everywhere that the function got called during a complex test. If you do this to enough functions, it's very useful for tracing existing behaviour in old codebases.
I feel, every time I read a C or C++ program, that half or more of it is just macros. I understand that macros can be cool but they are hard to track, debug, etc. Not to mention that most programming languages do not even define something like macros (although Perl6 will have something of the sort).
I personally always have found a way to write my code without using macros, whether it be with templates, multiple inheritance, etc. I have even felt I am not a good programmer because all the pros use macros and I try to avoid them as much as I can.
The question is, are there problems which cannot be solved without macros? Are macros ultimately a good/bad practice? When should I consider using a macro?
Yes, here's one. When you need to add tracing code to your program in such a way that one configuration contains it and the other completely omits you have to use macros.
Something like:
#ifdef WITH_LOGGING
#define LOG( x ) DoLog( x )
#else
#define LOG( x )
#endif
now you use it this way:
LOG( L"Calling blahblahblah with " + getSomeStringHardToCompute() );
and in the configuration with WITH_LOGGING you have that code and otherwise it is completely omitted - not even present in the binary, and therefore
it doesn't help others analyze your program
you get a smaller binary
the program doesn't waste time fo logging at all
the compiler can produce better optimized code.
You've been looking at some bad C++ code. The places I use macros are limited to:
header guards
very occasional conditional compilation
a general exception throwing macro
a general debugging/logging output macro
I don't think those four can be avoided.
Straight from Scott Myer's Effective C++ -> 1
Given the availability of consts and inlines, your need for the preprocessor is reduced, but it's not completely eliminated. The day is far from near when you can abandon #include, and #ifdef/#ifndef continue to play important roles in controlling compilation. It's not yet time to retire the preprocessor, but you should definitely plan to start giving it longer and more frequent vacations.
Debug behaviour may be controlled with constant flags or debug functions. So here is my list of unavoidables:
Multiple inclusion protection.
Macros are the only way of symbol stringification. assert macro, compact realization of const string & stringify(enum category value);
Example:
const char* stringify(enum category value)
{
#define c(x) case x: return #x;
switch(value) {
c(CIRCLE)
c(RECTANGLE)
c(TRIANGLE)
default: return "UNKNOWN";
}
#undef c // the most important part
}
Macros, of course, are also useful when you want to generate code during preprocessing. While this can be avoided using templates (see this SO question and discussion - Are C++ Templates just Macros in disguise?), you can use macros if it makes the life of your users easier - see how the 'googletest' project (https://github.com/google/googletest/) uses macros effectively. You obviously don't want to use macros to generate code that needs debugging, use templates instead.
I think that C++'s templates and inline functions make macros pretty much avoidable.
The ubiquitousness of macros is probably due to the fact that there are many C++ programmers that used to be C programmers. Such people will probably be proficient at using macros (because it sometimes really is the best or only solution in pure C) and might not see any point in learning the more complicated C++ features if they already know how to solve the problem. At least in the open source world, there are many C converts, so you naturally meet C paradigms. I don't think that you're a bad programmer if you avoid such a feature, many people do, just like GOTOs.
C (and therefore C++) is an extremely flexible programming language. This is great, because everyone can develop his own distinct style and solve most problems in several different ways. This, however, can also be considered a problem. In my opinion not a problem that should be solved by the language but by establishing conventions.
There are many features in C++ that can be safely ignored. Maybe there are weird special occasions where such a feature would really be the best approach, but in most cases, you can live without:
Friend classes
Macros
GOTOs
And more.
IMO, a senior C++ programmer should be able to at least read them all fluently - yet I expect a good programmer to consider carefully when and if to use an infamous feature.
There are many problems that I can't solve without macros.
For instance, serialization/deserialization of some structs
#define STRUCT_DESCRIPTION structname(MyStruct) member(int,a) member(double,b) member(long, c)
#include "declare_serializable_struct.h" // declares struct itself and generates serialization/deserializaton code
#undef STRUCT_DESCRIPTION
( BOOST_PP_SEQUENCE may also be used)
Another example - dispatching a messages using message map, i.e. generating switch like this:
switch(message_type)
{
case msg1: on_msg1(msg); break;
case msg2: on_msg2(msg); break;
...
}
and generate handler method declarations on_msgX(msg) in the same time using some message description table ("map")
Personally, I try to avoiod macros when possible, but I didn't succeed in this way.
However, lambdas in c++0x allows to inline arbitrary code into "user-or-library-defined languge statements" such a foreach loops, so macro realm lose a significant part :)
Macros are a solution for conditional compiling (by ifdef and ifndef). Here is the examples:
1)
#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
//...
#endif
2)
#ifdef __cplusplus
#define BEGIN extern "C" {
#define END }
#define NULL (0);
#else
#define BEGIN
#define END
#define NULL ((void*)0);
#endif
//-------------------------
BEGIN
void my_function(char* str);
END
//-------------------------
void my_function(char* str)
{
if(str != NULL)
{
//...
}
}
But inline functions and templates replaces other usages of macros in C++.
I tend to avoid using macros as much as possible because of their obvious safety / debugging issues, however there are times when macros offer something that no other facility within the language does as elegantly, in which case I prefer to use a macro just because it makes my life (and those of my fellow developers) easier.
For example, I have created an Enum class, which wraps an enum in a struct (scope) and adds some functionality:
possibility of iteration (which implies an order of the values)
conversion to / from string (handy to read/write to a file, write to logs)
In order to create the enum, I use a macro which will automatically generate the converter (to and from) and the vector for iteration.
Of course I could do without one, after all the macro is only for code generation. But doing without one would mean violating DRY, and in my little own preferences "DRY" > "Don't use macros". Because once debugged the macro is safe, whereas a DRY violation is a nightmare for maintenance.
Now, I am all for ditching this macro as soon as I find how not to violate DRY. Ideas are obviously welcome... and an external script is NOT better ;)
My 2 cents.
I try to avoid macros too, but to expand on the debugging, I have not found a way to print file name, function name, and line number when debugging.
I typically have a header file called DebugLog.h with the following Macro
#define DEBUG(debugMessage) \
printf("%s | %s [%d] - %s\n", __FILE__, __PRETTY_FUNCTION___, debugMessage);
Using:
DEBUG("Test")
will output something like:
main.cpp | foo(void)[20] - Test
You can adjust the macro for C++, and other debugging statements. It's also possible to modify the macro to send the resulting string to a logger.
I've started working at a telecom company. The product code base is about 20 years old, and has to support many legacy products, while also trying to avoid duplicate code. the language used is C++03. I find lots of contstructs similar to the following
ClassA::methodA(...)
{
// Common code
...
#if defined(PRODUCT_A) || defined(PRODUCT_B)
// Code for Product A or Product B
...
#elif defined(PRODUCT_C)
// Code for product C
...
#endif
// Common code
...
}
Horrible stuff, I agree. So far, we haven't been able to find a better solution. At least with this approach, we can understand what the code is supposed to do by simple code-reading.
The question is, are there problems which cannot be solved without macros?
No.
are macros ultimately a good/back practice? When should I consider to use a macro?
In languages which don't support or honor the inline keyword, macros are a great way to re-use code, but at the same time avoid the overhead of a function call in any code that is tightly looped enough for that to make a huge difference.
Your rant about code being littered with macros is probably justified. There are indeed hard to debug and in some cases to read. But they do come in useful in the very small number of cases where optimisation like this is truly warranted.
Note that as of C99, C can now do explicit inline functions using the inline keyword, which reduces the need for macros and even has advantages over using macros.
Programming language macros are good for what all macros are good for: avoiding typing the same things over and over again. So if you find yourself writing same pieces of code in many places, why not make a macro out of it? Especially if you're writing a library, using macros can make life easier for someone trying to use that library. Take a look at almost any GUI toolkit (Qt being one example). They all make extensive use of macros.
I have inherited a very long set of macros from some C algorithm code.They basically call free on a number of structures as the function exits either abnormally or normally. I would like to replace these with something more debuggable and readable. A snippet is shown below
#define FREE_ALL_VECS {FREE_VEC_COND(kernel);FREE_VEC_COND(cirradCS); FREE_VEC_COND(pixAccum).....
#define FREE_ALL_2D_MATS {FREE_2D_MAT_COND(circenCS); FREE_2D_MAT_COND(cirradCS_2); }
#define FREE_ALL_IMAGES {immFreeImg(&imgC); immFreeImg(&smal.....
#define COND_FREE_ALLOC_VARS {FREE_ALL_VECS FREE_ALL_2D_MATS FREE_ALL_IMAGES}
What approach would be best? Should I just leave well alone if it works? This macro set is called twelve times in one function. I'm on Linux with gcc.
Usually I refactor such macros to functions, using inline functions when the code is really performance critical. Also I try to move allocation, deallocation and clean up stuff into C++ objects, to get advantage of the automatic destruction.
If they are broken then fix them by converting to functions.
If they're aren't broken then leave them be.
If you are determined to change them, write unit-tests to check you don't inadvertently break something.
Ideally, I would use inline functions instead of using macros to eliminate function call overhead. However, basing from your snippet, the macros you have would call several nested functions. Inlining them may not have any effect, thus I would just suggest to refactor them into functions to make them more readable and maintainable. Inlining improves performance only if the function to be inlined is simple (e.g. accessors, mutators, no loops).
I believe this is your decision. If the macros are creating problems when debugging, I believe it is best to create some functions that do the same things as the macros. In general you should avoid complicated macros. By complicated I mean macros that do something more than a simple value definition.
Recommended:
// it is best to use only this type of macro
#define MAX_VALUE 200
The rest is not recommended (see example below):
// this is not recommended
#define min(x,y) ( (x)<(y) ? (x) : (y) )
// imagine using min with some function arguments like this:
//
// val = min(func1(), func2())
//
// this means that one of functions is called twice which is generally
// not very good for performance