Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a 'right' way to approach namespaces in C++

Tags:

c++

I'm infected by Java, C# and AS3, I keep wanting to use C++ namespaces in the same way but I keep reading that they're not really designed with this in mind.

Is there a correct way to use namespaces? For instance in a codebase consisting of a dozen library projects (let's say things like graphics, sound, math, etc) and a couple of application projects, what to do? Is it right/wrong/developer-preference:

  • To put everything a top-level MyCompanyName or MyProjectName namespace?
  • To have a (sub-)namespace for each library

Are there official rules/guidelines as part of C++, or only recommendations which people tend to follow?

like image 845
Mr. Boy Avatar asked Nov 02 '10 09:11

Mr. Boy


People also ask

Is it good practice to use namespace?

The statement using namespace std is generally considered bad practice. The alternative to this statement is to specify the namespace to which the identifier belongs using the scope operator(::) each time we declare a type.

How do you use namespaces correctly?

Typically, you declare a namespace in a header file. If your function implementations are in a separate file, then qualify the function names, as in this example. A namespace can be declared in multiple blocks in a single file, and in multiple files.

What is the correct syntax of defining a namespace?

Which is the correct syntax of declaring a namespace? namespace B{ int i; }; Take C++ Programming Practice Tests - Chapterwise! Explanation: A namespace definition always starts with the namespace keyword so definition with Namespace(capital N) is wrong.

Can you use namespaces in C?

No, C does not have a namespace mechanism whereby you can provide “module-like data hiding”.


1 Answers

As I mentioned in a comment on @Nim's answer, the key is really to come up with a structure that is practical.

If you look at, say, the .NET framework, its namespaces have long names and are deeply nested (Say, System.Collections.Generic.List<T>). The same applies to Java. You have hugely long names for hugely nested namespaces with no effect whatsoever.

The first time I create a List class, I'm going to run into name collisions, which is what namespaces were supposed to prevent. (Since this seemed to give a commenter the wrong idea, of course I am able to create my own List class. But every time I use it, I risk running into a conflict. The "standard" List, or its namespace, are both very commonly used, so there's a good chance I'll have a using on that namespace, which means that, if I also want to refer to my own List class in the same file, I get a conflict)

By contrast, the C++ standard library puts nearly everything in a simple std namespace (and a few things in std::ios)

In practical terms, the .NET namespaces are really a waste of effort. They have no effect. Every code file starts out with a long list of using X; using Y; using Z, so the net effect is that none of the namespaces are actually in effect when you write your code. In order to create a list of ints, I just do List<int>. The namespace is basically gone.

In C++, people are discouraged from using using namespace std, so in order to use a standard library symbol, we use the std prefix: std::vector<int>.

Boost uses something similar: nearly everything is in a boost root namespace. A few complex libraries are then placed in sub-namespaces, such as boost::filesystem. or boost::mpl, and some libraries have "internal use only" namespaces typically named aux, but they're intended to be invisible (or at least ignored) by the user.

This preserves the advantage of namespaces much better: they avoid naming conflicts. I can (and people often do, since vector can have several somewhat different meanings) define my own vector class, and it won't conflict with std::vector.

So how deeply nested should your namespaces be? I tend to go with something like the standard library, plus a bit. Don't invent new namespaces for everything, and keep namespace names short.

Perhaps all your company's code uses a common root namespace, say, Cpy.

Under this you might have a namespace for each product, say, Prod. And past that? Well, you might have a namespace for each major component (Comp), and that's basically it.

The important thing here is that you virtually never have to refer to the outermost namespaces. The code you write will be inside Cpy::Prod, so the only namespace prefix you're going to have to type out is Comp::, which is short and concise, like the standard library std. I virtually never have to write Cpy::Prod::Comp, because all my code is already inside the first two namespaces. If that wasn't the case, the namespace structure would be too long and too deeply nested.

Then I sometimes do like Boost, and create small "internal" helper namespaces, typically called Aux or Util or similar. These should be small, and should only ever be accessed from their immediate parent namespace. A specific component might have a few classes that are for internal use only. So they are tucked away in a small Aux namespace, mainly to keep them hidden from others that reference our component.

Of course, you might ask yourself what purpose the outermost "company" namespace really has. Isn't it a given that all our code is, well, our companys'? And third-party code will typically (hopefully) be inside its own namespace (say, boost::), so even without the company namespace, we shouldn't risk any conflicts. You might want to delete that one.

Another thing to consider is that if you're writing library components for external use, then the namespace structure should be even shorter. Inside the company, you can assume that everyone is already writing code inside the "company" namespace, so they never have to type out the namespace prefix. It's basically "free". But if external users have to refer to your code, it is an additional layer of namespaces they have to type out, which gets old fast. An overall "product" namespace is probably unavoidable (similar to std or boost), but then you might want to avoid the "product" namespace as often as possible. (Again, like both of these, which only rarely create sub-namespaces below the root namespace)

The bottom line is really that your namespaces have to be practical and usable. If you force users to type out more than, say, 8 characters in the namespace prefix, it gets annoying, and they'll just start putting using namespace X everywhere. You only really need namespaces where you might otherwise get name collisions. Code you control should never share a namespace with third-party code, because you have no control over what names they add (and usually, third-party libs take care of this by putting their library inside a common root namespace, such as boost). But among the code you control, there there aren't going to be that many collisions. So don't define more namespaces than you actually need.

like image 140
jalf Avatar answered Oct 14 '22 08:10

jalf