编译模板和/或使用模板编译的正确程序是什么?

发布于 2024-09-08 06:19:50 字数 239 浏览 3 评论 0 原文

我编写了一些模板类,它们是我需要编译的其他几个类的依赖项。关于如何在 Makefile 中执行此操作,我有几个选项:

  1. 每个需要模板的类都会列出其模板要求。这样做的缺点是每次我想添加新类时都需要重新创建依赖关系树。

  2. 以某种方式使模板成为目标。要么编译它们,要么创建一些不编译任何内容的影子依赖树,而只是在其中一个模板被修改时强制重新编译。

欢迎任何建议。

I have some template classes I've written that are dependencies for several other classes I need to compile. I have a few options as to how I can do this in my Makefile:

  1. Each class that requires a template lists its template requirements. This has the drawback of needing to recreate the dependency tree every time I want to add a new class.

  2. Make the templates into target somehow. Either by compiling them, or by making some shadow dependency tree that does not compile anything, but simply forces a recompilation in the event of one of the templates becoming modified.

Any suggestions are welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-09-15 06:19:50

正如尼尔·巴特沃斯(Neil Butterworth)在评论中提到的那样,用文件进行交易。假设您有一个 foo.cpp 和一个 bar.h。后者包含您的模板。前者可能会这样做,例如:

#include "bar.h"
class Foo : public Bar<Widget> { [...] };

虽然您的 Foo 类继承并因此依赖于您的 Bar 模板类,但您也已经使用 声明了文件依赖项#include 。

它与您在 Makefile 中指定的文件依赖项相同:

foo.o: foo.cpp bar.h
        g++ -I. -o foo.o foo.cpp

对于此规则,make 期望您指定的命令基于 foo.cpp 和 < code>bar.h 文件。如果您已经构建过一次 foo.o,并且这些依赖项没有更改,那么 make 知道它可以完全跳过该规则。

两次指定文件依赖项似乎很乏味,但幸运的是,GCC 可以使用 -M 命令从源代码中的 #include 自动生成 Makefile 中的依赖项 -线路参数。您可以在 gcc(1) 联机帮助页中了解这一点。只需获取 GCC 的输出,将其保存在某个位置(通常是 foo.d),然后将其包含到您的 Makefile 中。

通过一些技巧,您可以在构建应用程序的同一个 Makefile 中自动生成 *.d 依赖项文件。

As Neil Butterworth mentioned in a comment, make deals with files. Say you have a foo.cpp and a bar.h. The latter contains your template. And the former might do, for example:

#include "bar.h"
class Foo : public Bar<Widget> { [...] };

While your Foo class inherits and thus depends on your Bar template class, you are also already declaring your file dependencies with your #includes.

It's those same file dependencies that you specify in your Makefile:

foo.o: foo.cpp bar.h
        g++ -I. -o foo.o foo.cpp

For this rule, make expects that the commands you specify create foo.o, based on the foo.cpp and bar.h files. If you've already built foo.o once, and those dependencies haven't changed, make knows it can skip the rule altogether.

It may seem tedious to specify file dependencies twice, but luckily dependencies in your Makefile can be automatically generated from #includes in your source code by GCC using the -M command-line parameter. You can read about this in the gcc(1) manpage. Simply take GCC's output, save it somewhere, typically foo.d, and include that in your Makefile.

With some wizardry, you can automate the generation of *.d dependency files in the same Makefile that builds your application.

养猫人 2024-09-15 06:19:50

在选项 2 中,您可以使用 g++ 编译模板实例化。例如,假设您有:

// my_class.hpp
template <typename T1, class Container, typename Compare>
class my_class {
    // ...
};

并且在代码中使用了 my_class, std::greater ; >。使用 g++,您可以编译 my_class、std::greater 的实例化。 > 到目标文件中:

// my_class_long_long_vector_greater_instantiation.cpp
#include "my_class.hpp"

template class my_class<long, std::vector<long>, std::greater<long> >;

然后,在靠近底部的 Makefile 中添加:

my_class_long_long_vector_greater_instantiation.o: my_class.hpp

如果任何目标依赖于 my_class_long_long_vector_greater_instantiation.o,以及模板的声明my_class 已更改(my_class.hpp 文件已更改),然后 GNU make 将重新编译 my_class_long_long_vector_greater_instantiation.cpp,从而重新实例化 <代码>my_class, std::vector, std::greater; >。

另请参阅:模板在哪里?

On option 2, you can compile a template instantiation using g++. For example, suppose you had:

// my_class.hpp
template <typename T1, class Container, typename Compare>
class my_class {
    // ...
};

and in your code you used my_class<long, std::vector<long>, std::greater<long> >. With g++ you can compile the instantiation of my_class<long, std::vector<long>, std::greater<long> > into an object file:

// my_class_long_long_vector_greater_instantiation.cpp
#include "my_class.hpp"

template class my_class<long, std::vector<long>, std::greater<long> >;

Then, in your Makefile near the bottom you add:

my_class_long_long_vector_greater_instantiation.o: my_class.hpp

If any target depends on my_class_long_long_vector_greater_instantiation.o, and the declaration of template my_class has changed (the my_class.hpp file was changed), then GNU make will re-compile my_class_long_long_vector_greater_instantiation.cpp, hence re-instantiate my_class<long, std::vector<long>, std::greater<long> >.

See also: Where's the Template?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文