1

Say I have a file foo.hpp with a template

template<int a>
void foo()
{
    // Complex function
}

which I use in my main.cpp:

#include "foo.hpp"

int main()
{
    // quickly compiled code
    // ...

    foo<3>();

    // more quickly compiled code
}

Now each time I compile my project after changing main.cpp, foo<3>() needs to be compiled again, even though it doesn't change. The vast majority of the compile time is spent compiling foo<3>() in my case, so avoiding this is critical.

I would like to compile my project in two steps:

  1. Compile foo<3>(). This takes long but I only do it once.
  2. Compile main.cpp. This is now fast because foo<3>() is already compiled.

How can I achieve this behavior? I tried doing explicit instantiation in a different file and compiling this first, but main.cpp still takes the same time to compile.

Thanks for any help!

EDIT: Clarification of what I tried using explicit instantiation:

Create a new file precompiled.cpp:

#include "foo.hpp"

template void foo<3>();

Then tried compiling this first with g++ -c precompiled.cpp and afterwards, compile main.cpp using g++ precompiled.o main.cpp. But this instantiates foo<3>() again in step 2, which I want to avoid.

SirVivor
  • 85
  • 7
  • what did you do exactly when you tried explicit instantiation in a different file? – 463035818_is_not_an_ai May 22 '23 at 12:05
  • frankly, I am not sure if I do understand the question. If it is always `foo<3>` but never `foo<42>` then you do not need to instantiate the template in `main`. Just call `foo()`. If it is different numbers, you need to recompile – 463035818_is_not_an_ai May 22 '23 at 12:07
  • To clarify: I have some `main`, which I compile. Then I change something above the line `foo<3>()`, so `main` needs to be compiled again. This is where I want to avoid having to compile `foo<3>()` again as well. – SirVivor May 22 '23 at 12:16

3 Answers3

4

You're missing extern template void foo<3>(); in the header, after the definition of foo.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • That's interesting. I never saw this in our code before. Does this "trick" have a name? Is it commonly used? Is it a dirty hack or "clean code"? – Thomas Weller May 22 '23 at 12:29
  • 2
    @ThomasWeller This is [*explicit instantiation declaration*](https://en.cppreference.com/w/cpp/language/function_template#Explicit_instantiation), as opposed to *explicit instantiation definition* (which is the same thing but without `extern`, which must be used in a .cpp file in addition to this, as OP already does). I haven't seen anybody call this a hack. You you can use it to improve build times (as OP wants to do) or to expose templates from shared libraries. – HolyBlackCat May 22 '23 at 12:33
3

Templates need to be defined in headers (.hpp) and instantiated in compilation units (.cpp). Unlike regular classes, you cannot declare the function in a header and define it in a compilation unit, which would result in the compilation behaviour you expect: only recompile the function when it's instantiation changes.

I suggest wrapping all calls to your template in a separate .cpp and wrap those calls in functions that will be called from main.cpp. This way, you may modify other areas of main.cpp without recompiling foo. However foo will be recompiled if you change how you use it in the other unit.

Example: foo3.cpp:

#include "foo.hpp"

void foo3() {
    foo<3>();
}

foo3.hpp:

#pragma once

void foo3();

main.cpp:

#include "foo3.hpp"

int main()
{
    // quickly compiled code
    // ...

    foo3();

    // more quickly compiled code
}
deribaucourt
  • 424
  • 8
2

You cannot avoid instantiating foo<3> if you are using a function. Use this instead:

template<int a>
struct foo
{
    void operator()() {
        //complex code here
    }
};

Make a file say named bar.hpp with the following code

#include "foo.hpp"
struct foo_3 {
    static foo<3> fooinst = foo<3>();
    void operator()() {
        foo_3::fooinst();
    }
};

And then use bar.hpp (you are ALLOWED to precompile it returns a .gch file. Though I'm puzzled why you insist using the template.

jett8998
  • 888
  • 2
  • 15