Here are some reasons why and how C++ namespaces are different than Java or C# namespaces.
Avoiding conflicts
In Java/C# languages, namespaces are intended to avoid conflicts between names in different parts of class libraries. You may have class called "Watcher" in 5 different places in namespace hierarchy in C#. In C++, if you have same named classes occurring in your library then you put inside another class instead of creating namespaces. Such nested classes are all fine and encouraged and in fact the syntax also treats as if class is a namespace using :: operator.
How much nested namespaces should be?
Popular libraries like Boost, Eigen and of course, STL provides good examples. these libraries typically have pretty much everything stuffed in to one namespace like std::
or boost::
or eigen::
. Few components get their own namespace like std::ios
or boost:filesystem
. There is no consistent rules around when to use second level but it seems large or separately developed/maintained or optional components typically get their own namespaces. The third level is even more rare. Generally I use the structure company::project
and for large independently usable subsystem of projects company::project::component
.
Avoiding conflicts in external libraries
Now the big question: What if you get two libraries from two different people which has exact same namespaces and classes? This situation is fairly rare because most people tend to wrap their libraries at least in their project's name. Even if project names are same, its even rarer that you end up using libraries from both. However sometimes bad decisions are made for project names (ahm... "metro", "apollo" ...) or even namespaces are just not used at all. If that happens, you wrap #include for either or both libraries in to a namespace and conflict is resolved! This is one reason why people don't bother too much about conflicts because resolving them is trivial. If you follow the practice of using company::project
then conflicts become super rare.
Differences in languages
Although C++ provides using namespace
statement just like C#, its generally considered a bad practice to "import" everything in your own namespace. The reason for this is that a header can contain lots of "bad" stuff including redefining things that can totally surprise you. This is quite unlike C#/Java where you only get clean public interface when you do equivalent of using namespace
. (side note: in C++ you can achieve the same thing by using Pimpl pattern but its usually too much of extra plumbing and few libraries actually do it). So you almost never want to do using namespace
. Instead you do typedefs
(or using name =
) for what you actually want to use. This again makes deeply nested namespaces impractical to use.
Organizing code
In Java/C#, people tend to organize code in folders a lot. Typically as folder grows more than 20 or even 10 files, people would start thinking about folders. In C++, things are more diverse but for many large projects flatter directory structures are preferred. For example, standard library's std folder has 53 files and Facebook's folly project seems to go same route. I think one reason for this probably is the fact Java/C# folks use visual IDEs more and use mouse scrolls in folder navigation as opposed to console where you can use wild cards to find file in flat structure. Also C++ programmers absolutely don't shy away from putting multiple classes in single file and naming file as logical unit instead of same as class name unlike in C# or Java. This makes compilation faster which is very important for large projects. While there is no language-level requirement for having its own namespace for each folder many C++ developers prefers to assign its own namespace to each folder and keep folder hierarchy 2 or less levels deep.
Possible exception
In C++ you can refer to A::B::C::D
as just C::D
if you are already inside A::B
. So if you have private code or less used classes that you want to push further down then you might do so while still keeping your own relative depth to 2 or so. In this case, you might also want to create folder for each level just so file locations are predictable. In general, there are no gold standards in this area but you do not want to go overboard with deeply nested namespaces mimicking C#/Java.
Related