Question

I'm implementing a custom templated container as part of a learning project in C++. The container makes use of different components like serialization, memory management, iterators. I am wondering what is the best way to organise the code.

Option 1: Put everything into one header file:

I've seen this in several example online. But by doing this I'm going to end up with a file of several thousand lines long:

// container.hpp
template <typename params>
class Container {

public:
    // params is a struct with typedefs and static variables 
    // used to configure the container at compile time

    // I define additional typedefs and static variables here from params::

public:
    class iterator {

        // can use the typedefs and variables above
    };

    class memory {

        // can use the typedefs and variables above
    };
};

Option 2: Split the code into multiple headers

Each file contains the implementation of 1 component.

// memory.hpp
template <typename Container>
class memory {

public:
    // typedefs and static variables from Container::

};

// iterator.hpp
template <typename Container>
class iterator {

public:
    // typedefs and static variables from Container::

};

// container.hpp
#include "iterator.hpp"
#include "memory.hpp"

template <typename params>
class Container {
public: 
    // typedefs and static variables here from params::


    typedef Container<params> self_type;


    iterator<self_type> begin();

private:
    memory<self_type> mem;
};

What are the arguments to chose?

Solution 1 seems cleaner; something bugs me about having to pass the container type to the memory and iterators in solution 2. But at the same time the code is organised in different files in solution 2. Each file contains the implementation of 1 component.

Is it just a matter of personal preference? Or are there objective reasons to choose one solution over the other? Or is there a completely different and better approach?

Was it helpful?

Solution

Is it just a matter of personal preference or is there a reason why to choose one solution over the other ? (or a completely different approach).

No, that's not a matter of personal preference.

It's always better to have the several components being implemented in separate header files (as you suggest for your 2nd solution).

This will increase

  • readability
  • maintanability
  • reusability

OTHER TIPS

In short

Option 2 is better and there are objective reason for this. And yes, the approach can be improved.

More details: why option 2 is to be preferred

Option 1 lacks separation of concerns. What does this mean?

  • Imagine that one day your project could afford to hire a team, with an expert of serialization, another specialist for iteration, and a guru of memory management.
  • Option 1 would make it difficult for this hypothetical team to work together. They'd all work on the same file. And even with a good repository management, there would be merge conflicts and lots of disputes about who is in charge of what.

Option 2, defines clear boundaries between the components of your solution. This has lots of benefits:

  • smaller file that are easier to read: You can for example grasp what is in container.hpp without necessarily having to read iterator.hpp;
  • easier changes;
  • encourages potentially reusable sub-components.

More details: how to do better ?

You should include all your components in your own namespace. This is important, because in option 1 iterator is not exposed under its own name but as Container::iterator whereas in option 2, without namespace, it would be known as iterator which could create some ambiguities.

Another possible improvement, could be to separate the definition of each template class from its implementation in two files:

  • This multiplies of course the files. One could think it's of no use because the full code of the C++ templates must be included in the compilation units in which they are used.
  • But it brings the additional benefit of separating the interface from the implementation, at least in the source code.

Finally, you may find some more inspiration in the boost guidelines for headers.

Licensed under: CC-BY-SA with attribution
scroll top