Introduction
Namespaces are a very powerful C++ language feature. This article does not
teach you the syntax of namespaces. Rather, it shows you how to use them
properly.
Namespaces simply wrap all enclosed names with another name. For example:
namespace net {
class Socket {
...
};
}
...
net::Socket socket;
By doing that, they make sure that if two libraries both implement the Socket
class, if they name their namespaces differently your program can use both
without a conflict.
But this brings up another question: If two independent companies both decide
to write network libraries, what are the chances that they are going to
implement a class named Socket? My guess is somewhere around 100 percent.
We also like it when namespace names are easy to type, which means that they
should be 2-4 characters long. With that in mind, what are the chances that both
companies are going to name their namespace net? 5 percent? 10
percent?
Whatever it is, it shows that namespaces do not solve the problem, they only
make it less severe.
An Industrial Strength Solution
The solution to this problem is to use long, unique namespace names, and then
bring the namespaces into a program by using short aliases.
So a company writing the network library should write something like:
namespace net_33843894 {
class Socket {
...
};
}
where the number after net_
is going to be generated using a random
number generator. Say this code is placed in a header file called
<netlib>
Then the library is sold to a client, who decides to use it on a project. The
client then writes his own project-local header file named <mynetlib>,
with the following content:
#include <netlib>
namespace net = net_33843894;
He has just created a project-local alias for the namespace of his library
vendor. If the namespace name net had already been taken by another
library, the user can choose another name: net2, sock, or something else. There
will be no name conflicts.
Lowering Barriers
A smart thing to do with your library is to make it easy for people to start
using it. In an ideal world, they should be able to double-click on an
installation file and the library would be immediately available inside their
development environment. Next thing they are typing is #include <yourlib>
and they are using it to do something useful.
However, if the user has to make his own header for every header in your
library, then he has to suffer a little bit in order to use it. Not every user
will be willing to do so.
The solution to this problem is to provide reasonable defaults, but to let
the users cop out of them if they are not suitable. The way to do this is with
preprocessor directives in your header file:
namespace net_33843894 {
class Socket {
...
};
}
#ifndef NO_NET_33843894_ALIAS
namespace net = net_33843894;
#endif
This way, we provide a reasonable default for the namespace name. If that
name is already taken, then the user can define the macro NO_NET_33843894_ALIAS
and no alias will be defined.
Current Compilers
Error messages are already a nightmare with templates. With long namespace
names, we make them even worse.
Unfortunately, none of the compilers I use are smart enough to display an
error with the shortest available namespace alias at the point of error. So even
though you may be using the alias net, if you make an error using the Socket
class the error will mention net_33843894::Socket
. Not very readable.
So I use a little trick. It works only for headers that contain only inline
functions (as it affects the actual names used by the linker), but I have plenty
of those. If the macro NO_NET_33843894_ALIAS
is not defined, I use the short
name as the namespace name, and the long name as the alias:
#ifdef NO_NET_33843894_ALIAS
namespace net_33843894 {
#else
namespace net {
#endif
class Socket {
...
};
}
#ifndef NO_NET_33843894_ALIAS
namespace net_33843894 = net;
#endif
And the error messages become bearable again.
For more good stuff about C++, including a way to write code without memory
errors, visit http://www.jelovic.com.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.