mardi 31 octobre 2017

Fixing self-blocking includes in a module based library

I have written a simple templated, module-based header library. With module-based I mean that one can include only string.h or dynarray.h and the header will pull in all of its dependencies.

Now im facing an issue with missing types because of the way this system works. A module does:

  • #include all dependencies
  • Define an interface class Foo
  • #include an implementation file

Unfortunately in some situations two interfaces need to be available before including any implementations. I have broken down the problem here:

string.h

#pragma once

// A string depends on a DynArray.
#include "dynarray.h"

template<typename E>
class String {
public:
    DynArray<E> arr;
    /* ... */
};

// Include the implementation of all the different functions (irrelevant here)
#include "string_impl.h"

dynarray.h

#pragma once

// The dynarray header has no direct dependencies

template<typename E>
class DynArray {
public:
    /* ... */
    E& Get(int index);
};

// Include the implementation of all the different functions
#include "dynarray_impl.h"

dynarray_impl.h

#pragma once

// The dynarray implementation needs the OutOfRangeException class
#include "out_of_range_exception.h"

template<typename E>
E& DynArray<E>::Get(int index) {
    if (index >= size) {
        throw OutOfRangeException("Some error message");
    }
}

out_of_range_exception.h

class OutOfRangeException {
public:
    String message;
    OutOfRangeException(String message) {
        /* ... */
    }
};

Due to including the implementation of a module at its bottom, when including string.h somewhere, the content of dynarray_impl.h and with it out_of_range_exception.h comes before the string class interface. So String is not defined in OutOfRangeException.

Obviously the solution is to delay only the implementation part of dynarray (dynarr_impl.h) after definition of the string interface. The problem is that I have no idea how to do this without creating some kind of common header file, which is not compatible with a module based approach.

Aucun commentaire:

Enregistrer un commentaire