3

The replies in this post come very strongly against including headers inside a namespace and Doxygen is confused if that is done (which suggests that its team did not consider that usage either). I would like to ask whether including headers inside a namespace is justified in the following case.

I am developing a header-only framework for exploring a certain family of algorithms. Once first released, extensions in the form of header files will be contributed by the members of the research community. A contributed header file may implement a new algorithm or a policy of an existing algorithm or something else. Depending on what the new header implements, it will be placed in the relevant folder.

The namespaces in the framework mimic the folder structure. So, consider a folder A/B/ of the framework and suppose that the headers x.h, y.h and z.h are in that folder. Without including headers inside namespaces, the file x.h would look something like this:

namespace N { // The namespace in which the whole framework resides
namespace A { // Folder A/
namespace B { // Folder A/B/
namespace X { // The facilities provided by x.h are related
    ... // Definition of the facilities
}
}
}
}

The files y.h and z.h would begin with opening four namespaces as well. Furthermore, if a user contributes w.h to this folder, he will need to remember to open the namespaces N, A and B to not break the design.

In the alternative (and better in my opinion) design, each folder has a headers.h file as follows.

A/B/headers.h is:

namespace B {
    #include "x.h"
    #include "y.h"
    #include "z.h"
}

A/headers.h is:

namespace A {
    #include "B/headers.h"
    ... // includes headers.h of other sub-folders of A/
}

Then x.h looks like this

namespace X { // The facilities provided by x.h are related
    ...
}

Are there strong reasons not to use this alternative design?

Please note that the library is meant to be included into the .cpp as a whole (i.e. the top-level header.h is included). This does not incur long compile times, because the library is heavily templated and only a few templates (i.e. the algorithm under study, its policies and the related facilities) end up instantiated. Hence, I do not worry about the possibility of wrongly including an individual header without its namespace context.

There are no dependencies at the bottom (i.e. leaf) level, where all the headers implementing the actual facilities (such as x.h, y.h and z.h in the example) are located. So, a headers.h at the bottom level (such as A/B/headers.h in the example) may list the included headers in alphabetical order. A headers.h at a non-bottom level (such as A/headers.h in the example) includes headers.h from each sub-folder in the order that respects dependencies. That order is fixed (e.g. all the policies are included before all the algorithms) and the users will not need to deal with it.

  • 4
    I think this is more or less a duplicate of the linked question. You're trying to save a bit of typing and prevent a possible source of errors, but by doing that lose the ability to include individual headers – users must always include the top level header, or they get the wrong names. But now they get all declarations, not just those they need. That increases compile times. Also, you are unable to clearly track dependencies between headers – dependencies must be resolved by the include order in the parent headers. That all sounds far more frustrating than re-typing a couple of namespaces. – amon Nov 3 '16 at 7:29
  • 2
    One very strong drawback of the alternative is that people will not be consistently including only the top-level "headers.h", but also more specific headers like "A/B/x.h". This will result in parts of the library not being in the namespace where they were meant to be. – Bart van Ingen Schenau Nov 3 '16 at 7:31
  • @amon I edited the question to address your point. – AlwaysLearning Nov 3 '16 at 7:48
  • @BartvanIngenSchenau I edited the question to address your point. – AlwaysLearning Nov 3 '16 at 7:48
  • 1
    There's still the problem of tracking dependencies. Either there are no substantial dependencies within the project, and there's no reason to include the library as a whole. Or there are interdependencies between namespaces that make it very difficult to come up with a working include order. Usually, each file declares which headers it needs. Now, that information is implicit in the include order of all parents. You can't just order includes alphabetically. And do you require external headers? Those must come first in the top-level, making these declarations available to all your files. – amon Nov 3 '16 at 7:53
6

Reasons this is a bad idea:

  • Knowledge about your design is now partly stored in the directory structure. This isn't a good place for design logic to be placed.
    • What if someone just receives the file x.h? They won't be able to tell from the code itself what its classification is, because only with the full directory and all files can someone tell that x.h is properly located within N -> A -> B
    • There may be errors from accidentally putting something in the wrong place.
    • Logically, you would like someone who only has permission to use the parent to be able to extend it, but now you can only extend something that you have permission to modify it.
  • You can't add a new element just by adding a new header. Instead, you also have to update the appropriate "headers.h" file, leading to extra complexity and potential conflicts when adding new things.
  • You are making a design decision that the entire header file must be included forever. In your question, you note that this is not a problem right now. But are you really sure that there will never, ever be a time in the future where someone will want to include individual headers?
  • You are making a design decision that there cannot ever be significant interdependencies. Again, this is not true now, but are you really so sure it will never be true?
  • You are doing something weird which is a downside in itself, since now everyone using this code has to take time to learn your unique design, which no one else uses.

I would avoid this. Also, is it possible you should not be using nested namespaces?

  • This answer confuses between two separate issues: the issue of organizing code in folders the way it is organized right now (note that this organization prescribes a headers.h in each folder regardless of whether headers are included inside namespaces or not) and the issue of including headers inside namespaces. If the former is a given, would the latter present an additional problem? – AlwaysLearning Nov 3 '16 at 11:35
  • 1
    @AlwaysLearning organizing files into folders is logical, but the problem I have is that your design makes the folder structure the sole way the knowledge of the hierarchy is encoded. – user82096 Nov 3 '16 at 11:40
  • The design is well documented in the user documentation. Also, would moving the namespace declarations out of headers.h files (i.e. leaving only the include-directives there) into the leaf files (as shown at the beginning of the example for x.h) make things much better? – AlwaysLearning Nov 3 '16 at 12:10
  • 2
    @AlwaysLearning I think having the header itself define "what it is" is indeed better, because the information is in one place rather than spread through multiple folders/files. That way the header file stands on its own. – user82096 Nov 3 '16 at 17:08
  • 2
    @AlwaysLearning documentation could mitigate the problem of understanding what was done, but of course the ideal is self-documenting code that is clear on its own. – user82096 Nov 3 '16 at 17:10
2

As a general rule, I would never include a file within a namespace for the reasons dan1111 gives in his answer. If the purpose of your header is to share code, you are forcing users of your code to know details about your code structure and properly write the correct namespace before including the file.

In the case of a single header library, you can get away with it somewhat easier, but it still means you have to be consistent with your namespaces every time you include that file.

The one case I can see as acceptable is if the header is purely for preprocessor macros and you want to limit their scope. Something like:

namespace io
{
    enum class file_permissions
    {
        none = 0,
        execute = 1,
        write = 2,
        read = 4
    };

#include "enum_macros.hpp"
    GENERATE_ENUM_BITWISE_OPERATORS(file_permissions);
#include "enum_macros_cleanup.hpp"
}

Here the idea is to get the benefits of strongly typed enums while enabling users to combine the permissions flags, all without polluting the global namespace with macros any longer than we need to. Even here it feels a bit wrong to me and I generally prefer giving macros long names in all caps that are unlikely to conflict with anything else (or avoiding the macro completely).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.