Home > Software engineering >  If I've separated a template into a header and source, is there any way to compile it to its ow
If I've separated a template into a header and source, is there any way to compile it to its ow

Time:01-04

I like header files to exist as self-documenting references. I try to keep them to declarations with documentation comments, and then program all the implementation in my source files. Essentially a documented interface.

I'm working on a project making heavy use of templates and instead of filling up the header with implementation details (I know I could still declare the templates and define them later in the header but this doesn't solve this question) I've elected to do something like.

// foo.h
template<typename T>
class Foo {
public:
  Foo();
  T get_foo();
private:
  T foo;
}

#include "foo.tpp"
// foo.tpp
template<typename T>
Foo<T>(T f) : foo(f) {};

template<typename T>
T Foo<T>get_foo() { return foo; }

This has a moderate downside. Any source using #include "foo.h" must be fully recompiled any time foo changes. Essentially this has led to me needing to recompile most/all of the project every time I make a change in what is (conceptually but not practically) independent code.

I understand that due to either the way C compilers handle templates, or the language standard, or some combination thereof that when the compiler encounters a situation where substitution is needed like auto f = Foo<int>();, it needs the full definition of Foo<int> available to properly perform the substitution.

Is there no way at all around this? In this situation at least it seems to me that given foo.tpp as a source file the compiler could easily expand the template arguments for both and compile them as if they were a normal header/source file as a standalone TU. Then the linker just needs to find them later to resolve the definition of Foo<int> in the final linking stage.

Ostensibly this example is oversimplified and there are more complicated cases and caveats I've missed. I'm wondering though if there is a practical way around this. I'm considering writing a script to perform the substitution for me and then compiling those files, but was hoping there was a known and more generalized method.

CodePudding user response:

Is there no way at all around this?

Yes, there is. If you instantiate a template explicitly in the translation unit where the functions are defined, then you can use those instances in other translation units.

But that of course limits what template arguments can be used to those that you've chosen for explicit instantiation. For unconstrained template arguments, there's no way around defining the functions in all translation units (where they are ODR-used).

CodePudding user response:

No, except yes in two different ways.

The first way is to explicitly instantiate a template and its methods in a cpp file with specific arguments. Then the linker will find those implementations. This requires knowing which template arguments you plan on supporting.

The second is with modules, which no compiler has an industrial-quality implementation of. Modules avoids reparsing of the shared template code for each end user; recompilation nay still be required.

  •  Tags:  
  • Related