Use of macros: shouldn't be deprecated?

Sometimes I see an intensive use of macros in C++ code.

Shouldn't be much better to use generics instead? It's frustrating to debug code packed of macros: the debugger can't calculate the result of a macro (as it would happen using generics) therefore it's difficult to inspect data structures.

Does the ANSI C++ standard deprecate the use of macro? If not, why? When should I prefer to use macros instead of generics?

Thanks,
Dan
closed account (1yR4jE8b)
I think you are misunderstanding the use of Macros, they are not typically supposed to be used for template-like programming. You CAN use them in a similar fashion BUT you should not use Macros in places where templates are feasable. Macros are usefull for many other things than simply generic programming. It's the "Right Tool For The Right Job" idea.

There are many reasons why they can't be deprecated such as C++'s backwards compatibility, Include Guards and Conditional Compilation among many other things.

It can also be very frustrating to debug some of C++'s more ridiculous Template error messages ;-)

(sidenote: Generics are a Java idiom and are technically not at all like C++ templates, that's another thread however.)
Last edited on
Does the ANSI C++ standard deprecate the use of macro? If not, why?
No, because:
1. It would break millions of lines of code.
2. They're still too useful.
3. No one would enforce the deprecation anyway.

Consider this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define MINIMUM_PARAMETERS(n) if (params.size()<(n)) return INSUFFICIENT_PARAMETERS
#define GET_STRING_PARAMETER(dst,src) \
    if (params[src]->type!=STRING)\
        return EXPECTED_STRING;\
    (dst)=params[src]->value

Error dynamic_function_124(std::vector<dynamic_object *> &params){
    MINIMUM_PARAMETERS(2);
    //...
}
//...
Error dynamic_function_2033(std::vector<dynamic_object *> &params){
    MINIMUM_PARAMETERS(18);
    std::string s;
    GET_STRING_PARAMETER(s,2);
    //...
}

There's no way of implementing that other than using exceptions, and exceptions are undesirable in a variety of situations.
And of course there's less contrived examples, such as __LINE__ and __FILE__, _cplusplus, inclusion guards, compiler-defined macros that specify the target environment, and a very long etc.
It's a dog eat dog world out there and I feel your pain but helios is correct. There are many valid uses of macros. Unfortunately sometimes people get the wrong idea of what they are for. I once had to translate some bizarre code where macros were over used and it was like translating from one language into another (like chinese to english). The code was totally unreadable due to the excessive use of macros. It was like I had to go write down all the macros and then rewrite the code on paper with the macros expanded just so that I could understand what was happening, or use the preprocessor output to figure out what the program was doing. Unfortunately preprocessor output is not always very easy to read. You have to fight these battles in code reviews and make sure that you suggest alternatives when macros are used incorrectly.
Thank you guys for the details! Now I have a better understanding of when macros are a good solution and when it's bad to use them! :)
kempofighter: I wonder why there is so little IDE support for exploding macros.. Surely it should be easy and possible in all cases for the IDE to explode macros perfectly? (At least if the IDE isn't just an editor but also knows about the compiler invocation parameter, but that's true for a lot of IDE's out there)

The best I've seen are tooltips of the macro content, but why can't they visualize the macro expansion better? (Like code folding).


Maybe IDE vendors know more than we?

Maybe THEY already planning the deprecation? (Not the vendors.. I mean THEY.. you know.. ;)

Ciao, Imi.
The problem with asking IDEs to expand macros is that they have to know what macros are expanded to -- and they cannot. Something as simple as whether NDEBUG is defined can profoundly change a program. How does the editor choose between defined and undefined when both are legitimate values?
Well, VC++ doesn't seem to have troubles coloring code based on #if and friends.
Sure -- absolutely. But it cannot know that it is correctly highlighting the code. Or that "make release" will in any way compile code that resemble how the source was highlighted for the developer.

VC++ is a bit different because it integrates building and editing code in one platform in the typical case. It's a problem for IDEs like Eclipse, NetBeans, KDevelop, etc where the build rules for C++ programs typically live external to the project definition (in Makefiles).

Code like this is handled badly:
 
int x = FOO(y);


when FOO is defined only in a Makefile as an alias to some function. (This is an absurd simplification of what occurs deep in some code I've worked on recently.)

You really don't want to have to duplicate all of your Makefile rules inside your IDE's project definition.

The problem with macros is that external influences (parameters to the compiler) can fundamentally alter the way a given source file is parsed.
Last edited on
VC++ is a bit different because it integrates building and editing code in one platform in the typical case. It's a problem for IDEs like Eclipse, NetBeans, KDevelop, etc where the build rules for C++ programs typically live external to the project definition (in Makefiles).


Ok, I silently assumed, that the IDE knows very well about all the build options. This is certainly true for Visual Studio and I would have bet it is also true for Eclipse (but to be honest, I never used the C++ part of Eclipse). And last time I used Anjuta (or was it KDevelop?) they seemed to strive for the same goal and incooperating all possible options you could want to pass to GCC into an GUI.

I thought this was to be able to control the build options (at least I think that would be a very desireable goal for an IDE).


The system may not be perfect. There are always crude things like the "Additional Parameter" fields or even additional pre-build batch scripts who could alter the source or the build parameter and cannot be interpreted by the IDE.

But it would give a damn good visualization for 99.9% of the cases.


Ciao, Imi.
imi wrote:
The system may not be perfect. There are always crude things like the "Additional Parameter" fields or even additional pre-build batch scripts who could alter the source or the build parameter and cannot be interpreted by the IDE.

But it would give a damn good visualization for 99.9% of the cases.


In theory, that's true. In practice, not so much. The heavy users of C++ in the commercial world seem to find the most clever ways to break the ability of IDE's to accurately represent their code. This is especially true for those unfortunate people who have to support their C++ applications and libraries on multiple commercial Unix variants where the native C++ compiler is (to be utterly nice about it) non-conformant. The fun part: they all tend to be non-conformant in different ways. So using Eclipse, where it expects to use GCC, a fairly conformant compiler, in the background, is difficult at best.

If you want to read some sad commentary on the state of commercial software, read this: http://cacm.acm.org/magazines/2010/2/69354-a-few-billion-lines-of-code-later/fulltext
Wow...some of the quotes in that article were retarded..."It's ok, there is no malloc between the free() and the use!"
1
2
int a[2], b;
memset(a, 0, 12);

Theoretically, that should work. If a and b were placed next to each other in memory (as the programmer seems to think they are) it would work... but they might not be. :S
Anyway, wouldn't it be faster just to int a[2] = {0, 0}, b = 0;?

1
2
for (i = 1; i < 0; i++)
    ... deadcode ...

That's ridiculous. How could that loop ever run?

1
2
free(foo);
foo->bar = ...;

1
2
3
unsigned p[4];
...
p[4] = 1;

hurr

---
On topic:
---

Why would you want to deprecate the C preprocessor? Conditional compilation is extremely useful for writing portable code. Say you want to write a program that has to run on several architectures. So, somewhere presumably in a header file called something like "types.h" you have
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#if defined(__X86__)
typedef unsigned char  uint8;
typedef unsigned short uint16;
typedef unsigned long  uint32;
#elif defined(__X86_64__)
typedef unsigned char  uint8;
typedef unsigned short uint16;
typedef unsigned int   uint32;
#elif defined(__MIPS__)
...
#elif defined(__SPARC__)
...
#elif defined(__POWERPC__)
...
#endif 

how could you do that without macros? Also, header guards have been mentioned, etc.
Last edited on
Topic archived. No new replies allowed.