Namespaces and packaging in C ++

What is the best / cleanest way to use namespaces in packaged code?

eg. libraries like boost seem to have very organized namespace management, using some methods that eliminate name ambiguity. However, the important thing is that there will not be much code, for example

typedef namespace1::namespace2::sth_else::a_class<namespace3::namespace4::b_class> type; 

usually there are not many cross-names, which indicates a good architecture, but also good namespace management. The question is, what is good namespace management?

Say we have a file structure:

 component1/... (depends on reusable_if) component2/... (depends directly on reusable_if and on component 1) reusable/ reusable/some_part/ reusable/some_part/... reusable/some_other_part/ reusable/some_other_part/... reusable/SthThatUsesBothReusableParts.h (implements reusable_if/ISth.h) reusable/SthThatUsesBothReusableParts.cpp (implements reusable_if/ISth.h) reusable_if/ reusable_if/ISth.h (pure abstract class) reusable_if/ISthElse.h (pure abstract class) main.cpp (eg instantiates SthThatUsesBothReusableParts and passes to component1/2) 

The reason the reusable_if / folder exists is because both component1 and component2 want to reuse the same interfaces (therefore, none of them own "interfaces" exclusively). In addition, it is assumed that the project is really very large and requires its own namespaces for classes in each of the folders.

How would you apply namespaces in such a project? Let's say I declare all classes in a reusable / namespace ::reusable . Should I put interfaces from reusable_if in the ::reusable namespace or in ::reusable_if ? Or maybe there is none, since it is used by components 1 and component2?

What about namespaces in components 1 and component2? Anything to remember? What about the using keyword? Say I decided to add this namespace ::reusable_if . Can I put using reusable_if in the header files in components 1 and 2, provided that using ... is placed in the namespace ::component1 and ::component2 ?

I am open to any suggestions, as well as those that are not necessarily related to the above example.

+4
source share
2 answers

Here is what I use for my projects. My main rule is that each directory is a namespace, and each file is a class, with very few exceptions (sometimes I group helper functions in subdirectories of the detail namespace, but without another nested namespace).

  • Save the entire project inside the single top-level namespace specified after your project.

  • Store each utility component inside the top-level namespace, but in a separate directory. This is the only time I don't allow my namespaces to overlap with my directory tree.

  • Store each independently separable component inside your project, inside the nested namespace specified after your component. For convenience, provide a single header with a name after your component and containing the entire component interface either in the directory corresponding to your namespace or directly in the top-level directory of your project.

  • Save the implementation of each component inside the nested detail namespace. Unlike classes, the namespace does not support the language for private members, but the convention in Boost is that the detail namespace should not be directly called by user code.

No more nesting is required than project::component::detail::function() or project:::component::class.member() . If you provide complete interfaces that make ADL easier, you can reuse your component functions inside your project as function(x) for a variable x type project::component::class without worrying about name collisions.

Please note that in Uncle Bob's language: " reuse unit - release unit ." Each component should provide a bunch of coherent and interdependent classes and functions. In particular, for this component, it must provide a complete interface . C ++ supports this through argument-dependent search (ADL). See This Old Namespace Column and Interface Principle by Herb Sutter.

The presence of reuse_if and the presence of both component and reusable can be a smell of code, unless the considerations you mentioned in the comments apply. The component must be a release unit. If you can reuse a piece of code yourself, make it a separate component. If the code depends on another part, release it along with another code. See Sutter Column for these dependencies.

+3
source

Refusal of personal opinions. Your question mostly asks for subjective answers and is likely to be closed to him, but I will do it.


Namespaces are primarily useful to avoid identifier collisions. There is “your” namespace ( mylib:: and the namespace of everyone else ( std:: , boost:: , icu:: , ...), and that concerns the namespace being accepted.

There is little benefit in splitting your project (such as "your team project") into namespaces, unless you have a problem with identifier conflicts - in this case, you should reconsider your strategy for invoking your X and Y classes .; -)

In huge libraries, the situation is slightly different from Boost. They effectively consist of many different projects supported by individual teams, so there is a problem with the identifiers of a particular project that collided with each other if they are all focused on boost:: (and the collision may not appear during random testing).

If you stop looking at boost::filesystem as a “subtitle space” and instead look at boost:: as an “identity wrapper” for individual filesystem:: , thread:: , program_options:: projects and something else, so they look more "Boost-ish", the image becomes clearer.

+4
source

All Articles