Search code examples
c++headernamespacesincludeshared-libraries

Creating a namespace with code that is organized into different folders, and having a master header for library?


So I have project (named "vira") which produces both a shared library AND a set of executables (essentially some convenient tools built with the library for simple operations). Below is a simplified outline of the project to hopefully outline my question:

vira/
  | - external/
  |
  | - include/
  |      | - vira/
  |            | - models/
  |                  | - importers/
  |                           | - import_maplet.hpp             
  | - lib/
  |     | - models/
  |
  | - src/

Where external/ contains source code (unedited by this project) for small dependencies. include/vira/ contains all of the public headers, lib/ contains all of the implementation (and private headers) for the library, and src/ contains all of the headers/implementation for the executables. As you can see, the files in the lib/ directory are organized in subdirectories to try to group things together in a meaningful way.

I'm thinking of adding the entire library to a Vira namespace. However I'm unsure how exactly that would work with the folder structure I currently have (or if my folder structure is problematic).

Currently, to include import_maplet.hpp you would need to use:

#include "vira/models/importers/import_maplet.hpp"

When I look at other projects though, there is never such a mess of a long include statement. Take the chrono library for example. We simply using include <chrono> and now if we want to access the high resolution time right now, we then call in the code:

std::chrono::high_resolution_clock::now();

This seems like a more elegant solution. Or at least, this seems to be the solution that is more common in the c++ I have seen.

My first assumption on how to capture this kind of behavior is to keep my file structure, but then provide a "top level" header such as Vira.hpp and then setup a Vira namespace, a Models namespace, and an Importers namespace that are nested together such that you can simply use:

#include "Vira"

Vira::Models::Importers::import_maplet();

Taking a look at some other projects such as eigen do it, where you only need to do the following to include large swaths of the library:

#include <Eigen/Eigen>
#include <Eigen/Core>

But it leaves me with a two questions:

  1. While this approach seems common, I've also read that doing it this way will dramatically increase build time as it is including tons of headers, most of which would be unneeded. Does that mean that this style of thing is something I should avoid entirely?
  2. Whether I do it that way or not, should my code be organized into a namespace? It seems clunky to need both include "vira/models/importers/import_maplet.hpp" and to need to use Vira::Models::Importers::import_maplet();

Solution

  • Whether or not headers such as Eigen/Eigen are "bad" depends on how they are used and what the alternative is. If the alternative would lead to you including nearly all of the headers that Eigen/Eigen includes, then there is generally no significant downside to just including Eigen/Eigen. However, if Eigen/Eigen includes 20 headers and you really only need one... there could be a measurable impact to build times.

    In regards to namespaces, there are a few things to consider:

    1. namespaces do not have to match the folder/include structure. It may make sense to put everything in your project under one namespace or to have more namespaces than includes. This will depend on the size and purpose of your project.
    2. Cumbersome namespaces can be worked around with using namespace my::long::namespace (to get access to the whole namespace) or using my::long::namespace::class_i_want (to get access to a single class in the namespace) added to the top of a cpp file. Then you can just use class_i_want without a namespace.