C++ – Splitting and hiding headers in a static library

cheadersmaintainability

I am writing a static library for C/C++ (personal project). As my headers became rather large, I thought that splitting my headers would be a good idea.

Right now a header looks like this:

  • MainClass.hpp:

    • namespace impl: implementation details enclosed in a namespace impl
    • forward declarations of classes declared below (when needed)
    • MainClass declaration
    • MainClass free functions declarations
    • MainClass specialization declaration
    • MainClass specialization free function declarations
    • AuxiliaryClass1 declaration
    • AuxiliaryClass1 free functions declarations
    • AuxiliaryClassN declaration
    • AuxiliaryClassN free functions declarations
    • MainClass definition
    • MainClass free functions definitions
    • MainClass specialization definition
    • MainClass specialization free function definition
    • AuxiliaryClass1 definition
    • AuxiliaryClass1 free functions definitions
    • AuxiliaryClassN definition
    • AuxiliaryClassN free functions definitions

Where:

  • AuxiliaryClassK is a class logically or structurally related to MainClass (e.g. an iterator for MainClass, a nested class within MainClass, a derived class of MainClass etc.)
  • ClassX free functions as recommended in How Non-Member Functions Improve Encapsulation and Monoliths "Unstrung"
  • definitions are in header because they are templates.

This is becoming very crowded and difficult for me to navigate so I thought that splitting across multiple headers would help. However I do not know how to do it right.

Here is how I think the structure could look like:

  • MainClass.hpp:

    • forward declarations (when needed)
    • small classes/structs definitions & declarations
    • #include the other headers
  • _Class.hpp:

    • _Class declaration
    • _Class free functions declarations
  • _Class.inl:
    • _Class definition
    • _Class free functions definitions

With a _Class for each: MainClass, MainClass specialization, AuxiliaryClassK.

My questions are:

  • Is it reasonable to want to split a header (all are functionalities of MainClass) (I have headers over 1000 lines long and I foresee even longer ones) or should I leave it as it is?
  • Is the above split scheme ok? Should I further split a class and the free functions related to that class? Are there other solutions to make the code more maintainable?
  • How to hide the other headers (not in a sense of obfuscating / making the code unavailable, but avoid exposing the headers the users see (e.g. in a GUI with autocomplete)? They should include and be aware only of MainClass.hpp. Seeing other headers without being clear that they are behind–the–scenes headers will produce unnecessary confusion. One idea is to add a prefix like an _ (underscore) or to put them in a impl folder. (Again, this is not about hiding classes (I do that with a namespace), but to hide the split behind a header they should use).

Best Answer

You can do the following:

  • split the code into one class per header file.

  • in the case of templates, the implementation of the class functions can/should reside in the same header file (there is probably no scenario when you will want include the header, but not those definitions).

  • dependencies (your AuxiliaryClassK) should be #included instead of being defined directly. This makes your headers smaller, promotes code reuse (as you can include them - and only them - elsewhere) and keeps your code cleaner.

  • split your code into directories. The directory structure is normally a matter of policy; You could use your impl folder idea, or (for example) you could group them like boost does (one directory per functional area with all the implementation files, and one include file for convenience, which you can include in a single line in client code).

  • use pimpl idiom to minimize compile times.

As a rule, I would not use _Class file names. They are unusual (you increase the WTF/LOC measurement of your code which is never good).