自动将类定义与声明分开?
我正在使用一个几乎完全由头文件中的模板化类和函数组成的库,如下所示:
// foo.h
template<class T>
class Foo {
Foo(){}
void computeXYZ() { /* heavy code */ }
};
template<class T>
void processFoo(const Foo<T>& foo) { /* more heavy code */ }
现在这很糟糕,因为每当我包含其中之一时编译时间都难以忍受头文件(实际上我在每个编译单元中都包含了许多头文件)。
因为作为模板参数,我只使用一种或两种类型,所以我计划为每个库头文件创建一个仅包含声明的文件,而不包含大量代码,如下所示
// NEW: fwd-foo.h
template<class T>
class Foo {
Foo();
void computeXYZ();
};
template<class T>
void processFoo(const Foo<T>& foo);
:创建我需要的所有实例化的文件。 该文件可以一次性单独编译:
// NEW: foo.cpp
#include "foo.h"
template class Foo<int>;
template class Foo<double>;
template void processFoo(const Foo<int>& foo);
template void processFoo(const Foo<double>& foo);
现在我可以在代码中包含 fwd-foo.h
并且编译时间很短。 我将在最后链接到 foo.o
。
当然,缺点是我必须自己创建这些新的 fwd-foo.h
和 foo.cpp
文件。 当然,这是一个维护问题:当发布新的库版本时,我必须使它们适应该新版本。 还有其他缺点吗?
我的主要问题是:
我是否有机会从原始的 foo.h 自动创建这些新文件,尤其是
fwd-foo.h
代码>? 我必须对许多库头文件(可能是 20 个左右)执行此操作,并且自动解决方案最好,特别是在发布新库版本并且我必须对新版本再次执行此操作的情况下。 有任何工具可用于此任务吗?
编辑:
附加问题:在这种情况下,新支持的 extern
关键字如何帮助我?
I am using a library that consists almost entirely of templated classes and functions in header files, like this:
// foo.h
template<class T>
class Foo {
Foo(){}
void computeXYZ() { /* heavy code */ }
};
template<class T>
void processFoo(const Foo<T>& foo) { /* more heavy code */ }
Now this is bad because compile times are unbearable whenever I include one of those header files (and actually I include many of them in each of my compilation units).
Since as a template parameter I only use one or two types anyway I am planning to create, for each library header file, a file that contains only declarations, without the heavy code, like this:
// NEW: fwd-foo.h
template<class T>
class Foo {
Foo();
void computeXYZ();
};
template<class T>
void processFoo(const Foo<T>& foo);
And then one file that creates all the instantiations that I'll need. That file can be compiled separately once and for all:
// NEW: foo.cpp
#include "foo.h"
template class Foo<int>;
template class Foo<double>;
template void processFoo(const Foo<int>& foo);
template void processFoo(const Foo<double>& foo);
Now I can just include fwd-foo.h
in my code and have short compile times. I'll link against foo.o
at the end.
The downside, of course, is that I have to create these new fwd-foo.h
and foo.cpp
files myself. And of course it's a maintenance problem: When a new library version is released I have to adapt them to that new version. Are there any other downsides?
And my main question is:
Is there any chance I can create these new files, especially fwd-foo.h
, automatically from the original foo.h
? I have to do this for many library header files (maybe 20 or so), and an automatic solution would be best especially in case a new library version is released and I have to do this again with the new version. Are any tools available for this task?
EDIT:
Additional question: How can the newly supported extern
keyword help me in this case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我们使用 lzz 将单个文件拆分为单独的标头和翻译单元。 默认情况下,它通常也会将模板定义放入标头中,但是,您可以指定不希望发生这种情况。
为了向您展示如何使用它,请考虑以下内容:
获取上述文件并将其复制到“t.lzz”文件。 根据需要将任何 #include 指令放入单独的 $hdr 和 $src 块中:
现在最后,对文件运行 lzz,指定它将模板定义放入源文件中。 您可以在源文件中使用 $pragma 来执行此操作,也可以使用命令行选项“-ts”:
这将生成以下文件:
并且:
然后您可以运行这些通过一些 grep/sed 命令来删除 LZZ 辅助宏。
We use lzz which splits out a single file into a separate header and translation unit. By default, it would normally put the template definitions into the header too, however, you can specify that you don't want this to happen.
To show you how you might use it consider the following:
Take the above file and copy it to 't.lzz' file. Place any #include directives into separate $hdr and $src blocks as necessary:
Now finally, run lzz over the file specifying that it places the template definitions into the source file. You can either do this using a $pragma in the source file, or you can use the command line option "-ts":
This will result in the following files being generated:
And:
You can then run these through some grep/sed commands to remove the LZZ helper macros.
尝试使用预编译头。 我知道 GCC 和 MSVC 支持此功能。 不过,用法是特定于供应商的。
Try using precompiled headers. I know GCC and MSVC support this feature. Usage is vender-specific, though.
我已经研究同一个问题很长一段时间了。 在您提出的解决方案中,您定义了两次模板类。 如果它定义相同的东西(以相同的顺序)就可以了,但是迟早你肯定会遇到问题。
我的想法是从相反的角度考虑问题。 只要您没有专门化您的实现,它就可以正常工作。
它使用两个宏,这样就不必更新实现文件中的模板参数(但是,如果您想向类添加默认模板参数,请小心)。
通过这样做,您基本上以与非模板类相同的方式工作(当然,您可以使用模板函数执行相同的操作)。
编辑:关于 c++0x 中的 extern 关键字
我相信 c++0x 中的 extern 关键字会有所帮助,但它不会神奇地解决所有问题!
从这篇文章,
I have been working on the very same issue for quite a while now. In the solution you're proposing, you are defining your template classes twice. It will be ok if it defines the same stuff (in the same order), but you're bound to have problems sooner or later.
What i have come up with is to consider the problem the other way around. As long as you are not specializing your implementation, it works gracefully.
It uses two macros, which avois having to update template arguments in implementation file (be careful, though, if you want to add default template arguments to the class).
By doing this, you essentially work the same way you do with non-template classes (you can do the same thing with template functions, of course).
EDIT : about the extern keyword in c++0x
I believe the extern keyword in c++0x will help, but it won't solve everything magically !
From this article,
C++0x 将修复外部模板的编译时问题。 不过,我不知道如何自动执行您的要求。
C++0x will fix your compile time issues with extern templates. I don't know an automatic way to do what you ask, though.