Article Discussion
Reducing Preprocessor Namespace Pollution
Summary: Trampling roughshod over the global namespace (and all other namespaces) with the macro preprocessor is one of the least friendly things you can do in C++. Why, then, is it the case that many popular APIs do exactly that? The authors look at this nasty problem, and demonstrate a simple technique that can be used to obviate it, and be good C++itizens.
10 posts on 1 page.      
« Previous 1 Next »
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: March 8, 2005 11:09 AM by József
Chuck
Posts: 32 / Nickname: cda / Registered: February 11, 2003 0:06 PM
Reducing Preprocessor Namespace Pollution
November 6, 2004 2:00 PM      
The authors look at the nasty habit that many popular APIs
have of Trampling roughshod over the global namespace (and all other namespaces) with the macro preprocessor, and demonstrate a simple technique to obviate it, and still be a good C++itizen.

A regular installment in the Smart Pointers series.

http://www.artima.com/cppsource/reducepnp.html
Daniel
Posts: 5 / Nickname: teske / Registered: October 3, 2004 4:54 PM
Re: Reducing Preprocessor Namespace Pollution
November 6, 2004 6:56 PM      
http://www.artima.com/cppsource/reducepnp.html

Hmm, I get a 404 Error (Document not found.)
Are you sure that it is where it's supposed to be?
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
Re: Reducing Preprocessor Namespace Pollution
November 6, 2004 11:16 PM      
> http://www.artima.com/cppsource/reducepnp.html
>
> Hmm, I get a 404 Error (Document not found.)
> Are you sure that it is where it's supposed to be?

Sorry about that. The problem has been fixed.
Vesa
Posts: 5 / Nickname: vkarvone / Registered: June 14, 2004 5:19 AM
Re: Reducing Preprocessor Namespace Pollution
November 7, 2004 11:43 AM      
Well, what can I say. Silly use of macros is, well, just silly. In the running example, for instance, no reason was given (or I missed it) as to why it wasn't originally deemed possible to simply declare TheFunc as a function in the first place:

ACMELIB_EXTERNC void TheFuncST(void);

#ifdef ACMELIB_MULTI_THREADING_SUPPORTED
ACMELIB_EXTERNC void TheFuncMT(void);
#endif

ACMELIB_EXTERNC void TheFunc(void);

And define it in the AcmeLib:

void TheFunc(void) {
#ifdef ACMELIB_MULTI_THREADING
TheFuncMT();
#else
TheFuncST();
#endif
}

The overhead would almost certainly have been negligible.

Of course, it is good to point out silly uses of macros, but simplistically quoting the words of a master is more likely to lead to holy wars than enlightenment.
Matthew
Posts: 20 / Nickname: bigboy / Registered: June 14, 2004 10:43 AM
Re: Reducing Preprocessor Namespace Pollution
November 7, 2004 1:23 PM      
The clue is in the question, so to speak: It's AcmeLib, i.e. Lib. That is to say it's a library.
indranil
Posts: 8 / Nickname: indranil / Registered: November 7, 2004 8:29 AM
Re: Reducing Preprocessor Namespace Pollution
November 7, 2004 1:42 PM      
What do people think of the proposed #scope extension to the language. As suggested by Stroustrup himself?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1625.pdf

He proposes new keywords #scope and #endscope which can mark regions inside a file. Macros defined within a scope are only valid within the scope. #export keyword is available if you want a macro to be visible outside the current scope.
#import must be used to use an exported macro from another scope.

Does anyone know if this is going to be part of the upcoming standard?
Vesa
Posts: 5 / Nickname: vkarvone / Registered: June 14, 2004 5:19 AM
Re: Reducing Preprocessor Namespace Pollution
November 7, 2004 2:01 PM      
> The clue is in the question, so to speak: It's
> AcmeLib, i.e. Lib. That is to say it's a library.

And the library can't define the function TheFunc?

I'm not convinced.

In the article you specifically speak of different builds:

"These five lines [...] select the appropriate version of TheFunc based on whether the current build settings are specifying a single-threaded, or a multi- threaded, compilation."

I would expect that there were two versions (builds) of the lib. One version that contains the TheFuncMT (the multi-threaded version) and another version that doesn't. In fact, that is how it is usually done. I see no reason why both of the libraries couldn't also contain the TheFunc, which would call the appropriate function (either TheFuncST or TheFuncMT) "as a convenience to the user".

I agree that one shouldn't use macros for the purpose described in the article. It is almost never necessary even in C. Furthermore, the use of inline functions would also be possible in C99. However, the article, like categorically almost all articles and books dealing with or mentioning (C preprocessor) macros take a very simplistic attitude saying essentially that "macros are Bad, because authority X says so".

It is no wonder we see really silly uses of macros. None of the people who know better are thoroughly explaining why macros may be bad and how one might define well behaving macros. When people invariably end up using a macro for some purpose the result is a disaster. In my opinion, this article is a "start", but it stops very short---too short.
Matthew
Posts: 20 / Nickname: bigboy / Registered: June 14, 2004 10:43 AM
Re: Reducing Preprocessor Namespace Pollution
November 9, 2004 4:12 PM      
> And the library can't define the function TheFunc?

Of course it can. It does not for pedagogical reasons. Without wishing to sound offensive, I would have thought that was obvious.

> I'm not convinced.

> In the article you specifically speak of different builds:

> "These five lines [...] select the appropriate version of TheFunc based on whether the current build settings are specifying a single-threaded, or a multi- threaded, compilation."

> I would expect that there were two versions (builds) of the lib. One version that contains the TheFuncMT (the multi-threaded version) and another version that doesn't. In fact, that is how it is usually done. I see no reason why both of the libraries couldn't also contain the TheFunc, which would call the appropriate function (either TheFuncST or TheFuncMT) "as a convenience to the user".

Of course. In the vast majority of cases one does exactly that. But not in all cases; I have myself, on rare occasions, written binary libs which provide single and mult-threaded versions of a component, which are implemented internally as different instantiations of a template. Hence, your implied criticism of the pure, and therefore fatuous, pedagogy doesn't hold, at least not IMO.

> I agree that one shouldn't use macros for the purpose described in the article.

Ok

> It is almost never necessary even in C.

Disagree

> Furthermore, the use of inline functions would also be possible in C99.

Good point. We considered whether to include this, but it got lost in the wash, and the desire for brevity. That was probably a mistake, and I expect we'll find a point to add this in.

> However, the article, like categorically almost all articles and books dealing with or mentioning (C preprocessor) macros take a very simplistic attitude saying essentially that "macros are Bad, because authority X says so".

Well, maybe that's how you read it, but I don't think it gives that message. I think the section "Can good C-itizens still get caught?" counters your assertion.

> It is no wonder we see really silly uses of macros. None of the people who know better are thoroughly explaining why macros may be bad and how one might define well behaving macros. When people invariably end up using a macro for some purpose the result is a disaster.

This is the second time you've stipulated we should "know better" (http://www.artima.com/forums/flat.jsp?forum=226&thread=73370). ;)

Anyway, I disagree completely with this completely. The article ably demonstrates how the use of TheFunc macro is bad. How could its effects be called "good"??

> In my opinion, this article is a "start", but it stops very short---too short.

Then front up and write the rest of the picture. I have no doubt that Chuck would love to have a submission from you, and I'm always interested in learning more.

Cheers

Matthew
Gregg
Posts: 28 / Nickname: greggwon / Registered: April 6, 2003 1:36 PM
Re: Reducing Preprocessor Namespace Pollution
December 19, 2004 10:25 AM      
> The authors look at the nasty habit that many popular APIs
> have of Trampling roughshod over the global namespace (and
> all other namespaces) with the macro preprocessor, and
> demonstrate a simple technique to obviate it, and still be
> a good C++itizen.

I've written plenty of C and some C++ in the past. But I mostly went from C to Java to completely avoid all of this hog wash. Java, the platform, eliminates all of the mickey mouse #ifdef usage typical in a multi-platform C or C++ program/library. Java, the language, because of the underlying platform, has a lot less of these issues. And because of Java's dynamic class loading, the Factory model can be used to dynamically load the correct implementation of a particular interface for the deployment.

A lot of people just don't understand the powerful simplification of portability that Java provides. I won't summarily say that you can replace your use of C++ with Java, but I will say that there are a lot more reasons to use Java in the domains that I'm working in, than to use C++. But, of course everyone has different needs.

I also tend to choose to work in areas where I can use Java so that I don't have to fight those battles. I find myself getting a lot more done in a shorter time using Java than I ever did with C or C++. Most of my C++ experience is using VC++ on windows and the macro nightmare there is just scarey.
József
Posts: 2 / Nickname: jmihalicza / Registered: March 8, 2005 6:03 AM
Re: Reducing Preprocessor Namespace Pollution
March 8, 2005 11:09 AM      
What about using namespace aliases?

// in the lib:
namespace SingleThreaded {
void Func ();
}

namespace MultiThreaded {
void Func ();
}

// user code:
#include "Setup.h"
// ...
ThreadPolicy::Func ();

// Setup.h:
namespace ThreadPolicy = MultiThreaded;
10 posts on 1 page.
« Previous 1 Next »