英文:
Class template with interface and implementation in separate files
问题
I have some template classes that are separated into header files and implementation files:
// MyTemplate.h
template<class T>
class MyTemplate {
public:
void Foo();
};
// MyTemplate.cpp
#include "MyTemplate.h"
template<class T>
void MyTemplate<T>::Foo() {
// ...
}
To use MyTemplate
in another translation unit I can #include
the implementation file:
#include "MyTemplate.cpp"
template class MyTemplate<int>;
This way I get to:
- Keep the interface and implementation in separate files.
- Not have to maintain a list of all template instantiations in the implementation file.
I am in the process of converting to C++ modules. Is there any way to achieve the same with modules, when I should no longer use #include
?
英文:
I have some template classes that are separated into header files and implementation files:
// MyTemplate.h
template<class T>
class MyTemplate {
public:
void Foo();
};
// MyTemplate.cpp
#include "MyTemplate.h"
template<class T>
void MyTemplate<T>::Foo() {
// ...
}
To use MyTemplate
in another translation unit I can #include
the implementation file:
#include "MyTemplate.cpp"
template class MyTemplate<int>;
This way I get to:
- Keep the interface and implementation in separate files.
- Not have to maintain a list of all template instantiations in the implementation file.
I am in the process of converting to C++ modules. Is there any way to achieve the same with modules, when I should no longer use #include
?
答案1
得分: 2
在模块中,这可以通过简单地创建一个接口分区来轻松完成。这必须是一个 接口 分区,因为模板定义仍然是你的接口的一部分,所以它必须对导入它的人可见(就像常规的C++一样)。
这是如何完成的:
//主接口模块
export module MyTemplates;
export import :TemplateDef;
//您模块的其他内容。
//模板的定义
export module MyTemplates:TemplateDef;
import :TemplateDecl;
template<class T>
export void MyTemplate<T>::Foo() {
// ...
}
//模板的声明
export module MyTemplates:TemplateDecl;
template<class T>
export class MyTemplate {
public:
void Foo();
};
话虽如此,因为定义必须对所有人都可用,将它们分为两个文件几乎没有什么好处。如果更改定义文件,导入模块的所有人仍然必须重新编译。这就是模板的工作方式。
请注意,你的代码的非模块形式相当糟糕。将模板实现与接口分开是可以的;但使用名为 ".cpp" 的文件是不可以的。头文件是用来包含的;这就是为什么我们称它们为 "头文件" 的原因。当用户看到一个扩展名为 ".cpp" 的文件时,他们会假设它 不 应该被包含。
只需在两者都使用 ".h" 扩展名。 ".hxx" 也经常用于实现(应该由 ".h" 版本包含)。
英文:
In modules, this is trivially done by simply creating a interface partition. This has to be an interface partition because the template definition is still part of your interface, so it has to be visible to those importing it (just like regular C++).
This is done as follows:
//Primary interface module
export module MyTemplates;
export import :TemplateDef;
//Other stuff for your module.
//Definition for your template.
export module MyTemplates:TemplateDef;
import :TemplateDecl;
template<class T>
export void MyTemplate<T>::Foo() {
// ...
}
//Declaration for your template
export module MyTemplates:TemplateDecl;
template<class T>
export class MyTemplate {
public:
void Foo();
};
That being said, because definitions have to be made available to everyone, there's little to be gained by separating these into two files. If you change the definition file, everyone importing your module still has to be recompiled. That's just how templates work.
Note that the non-modular form of your code is pretty bad. Separating template implementation from interface is fine; doing it with a file named ".cpp" is not. Headers are meant to be included; that's why we call them "headers". The assumption a user will make upon seeing a file with the ".cpp" extension is that it is not supposed to be included.
Just use the ".h" extension with both. ".hxx" is also often used for the implementation (which should be included by the ".h" version).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论