我怎么避免每次编译项目时重新编译特定的模板函数?

huangapple go评论67阅读模式
英文:

How can I avoid recompiling a specific template function each time I compile my project?

问题

我有一个名为foo.hpp的文件,其中包含一个模板:

template<int a>
void foo()
{
    // 复杂的函数
}

我在main.cpp中使用它:

#include "foo.hpp"

int main()
{
    // 快速编译的代码
    // ...

    foo<3>();

    // 更多快速编译的代码
}

现在,每次我修改main.cpp并重新编译项目时,需要重新编译foo<3>(),尽管它没有更改。在我的情况下,绝大多数编译时间都花在重新编译foo<3>()上,因此避免这种情况非常重要。

我想将项目分为两个步骤:

  1. 编译foo<3>()。这需要时间,但只需执行一次。
  2. 编译main.cpp。现在很快,因为foo<3>()已经编译好了。

如何实现这种行为?我尝试在不同的文件中进行显式实例化,然后首先编译它,但main.cpp的编译时间仍然相同。

感谢任何帮助!

编辑:
关于我尝试使用显式实例化的澄清:

创建一个新文件precompiled.cpp

#include "foo.hpp"

template void foo<3>();

然后尝试首先使用g++ -c precompiled.cpp编译这个文件,之后使用g++ precompiled.o main.cpp编译main.cpp。但这会在步骤2中再次实例化foo<3>(),我想避免这种情况。

英文:

Say I have a file foo.hpp with a template

template&lt;int a&gt;
void foo()
{
    // Complex function
}

which I use in my main.cpp:

#include &quot;foo.hpp&quot;

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

    foo&lt;3&gt;();

    // more quickly compiled code
}

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

I would like to compile my project in two steps:

  1. Compile foo&lt;3&gt;(). This takes long but I only do it once.
  2. Compile main.cpp. This is now fast because foo&lt;3&gt;() 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 &quot;foo.hpp&quot;

template void foo&lt;3&gt;();

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&lt;3&gt;() again in step 2, which I want to avoid.

答案1

得分: 4

你在头文件中漏掉了extern template void foo&lt;3&gt;();,这应该在foo的定义之后。

英文:

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

答案2

得分: 3

模板需要在头文件(`.hpp`)中定义,并在编译单元(`.cpp`)中实例化。与常规类不同,你不能在头文件中声明函数并在编译单元中定义它,否则会导致编译行为不符合预期:只有在实例化更改时才重新编译函数。

建议将对模板的所有调用包装在单独的 `.cpp` 文件中,并将这些调用包装在从 `main.cpp` 调用的函数中。这样,您可以修改 `main.cpp` 的其他部分而无需重新编译 `foo`。但是,如果您更改在另一个单元中使用它的方式,将重新编译 `foo`。

示例:
`foo3.cpp`:
```CPP
#include "foo.hpp"

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

foo3.hpp

#pragma once

void foo3();

main.cpp

#include "foo3.hpp"

int main()
{
    // 快速编译的代码
    // ...

    foo3();

    // 更多快速编译的代码
}
英文:

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 &quot;foo.hpp&quot;

void foo3() {
    foo&lt;3&gt;();
}

foo3.hpp:

#pragma once

void foo3();

main.cpp:

#include &quot;foo3.hpp&quot;

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

    foo3();

    // more quickly compiled code
}

答案3

得分: 2

你无法避免实例化 `foo&lt;3&gt;`,如果你正在使用一个函数。请使用以下替代:

```cpp
template&lt;int a&gt;
struct foo
{
    void operator()() {
        // 复杂的代码在这里
    }
};

创建一个名为 bar.hpp 的文件,其中包含以下代码:

#include &quot;foo.hpp&quot;
struct foo_3 {
    static foo&lt;3&gt; fooinst = foo&lt;3&gt;();
    void operator()() {
        foo_3::fooinst();
    }
};

然后使用 bar.hpp(你可以预编译它并生成 .gch 文件,尽管我对你坚持使用模板感到困惑。)


<details>
<summary>英文:</summary>

You cannot avoid instantiating `foo&lt;3&gt;` if you are using a function. Use this instead:
```cpp
template&lt;int a&gt;
struct foo
{
    void operator()() {
        //complex code here
    }
};

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

#include &quot;foo.hpp&quot;
struct foo_3 {
    static foo&lt;3&gt; fooinst = foo&lt;3&gt;();
    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.

huangapple
  • 本文由 发表于 2023年5月22日 20:04:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76306016.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定