接口和实现位于单独文件中的类模板

问题描述 投票:0回答:2

我有一些模板类,它们分为头文件和实现文件:

// MyTemplate.h
template<class T>
class MyTemplate {
public:
    void Foo();
};
// MyTemplate.cpp
#include "MyTemplate.h"
template<class T>
void MyTemplate<T>::Foo() {
    // ...
}

要在另一个翻译单元中使用

MyTemplate
,我可以
#include
实现文件:

#include "MyTemplate.cpp"
template class MyTemplate<int>;

这样我就可以:

  1. 将接口和实现保存在单独的文件中。
  2. 不必在实现文件中维护所有模板实例化的列表。

我正在转换为 C++ 模块。当我不再使用

#include
时,有什么方法可以通过模块实现相同的效果吗?

c++ templates c++-modules
2个回答
3
投票

在模块中,只需创建一个接口分区即可轻松完成此操作。这必须是一个 interface 分区,因为模板定义仍然是接口的一部分,因此它必须对导入它的人可见(就像常规 C++ 一样)。

按如下方式完成:

//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();
};

话虽这么说,因为定义必须提供给每个人,所以将它们分成两个文件几乎没有什么好处。如果更改定义文件,则每个导入模块的人仍然需要重新编译。这就是模板的工作原理。


请注意,代码的非模块化形式非常糟糕。将模板实现与接口分离是可以的;使用名为“.cpp”的文件来执行此操作是不是。标头是要包含在内的;这就是为什么我们称它们为“标题”。用户在看到扩展名为“.cpp”的文件时会做出的假设是,该文件应该被包含在内。

只需使用“.h”扩展名即可。 “.hxx”也经常用于实现(应该包含在“.h”版本中)。


0
投票

在不使用模块的情况下,我发现人们通常有两种方法:

  1. 有两个“头”文件:
    file.h
    file_impl.h
    。您可以在
    file_impl.h
    末尾添加
    file.h
    。这与在文件末尾的类声明之后的所有模板定义基本相同。这就是我现在所做的。
  2. 有 1 个“标题”和 1 个“cpp”:
    file.h
    file.cpp
    。然后,您在
    .cpp
    文件末尾进行一些显式实例化。
    .cpp
    必须被编译和链接。缺点是您必须先定义允许哪些模板实例化,并且不能(您不能???)使用其他类型。

我想建议第三种方法。我会在我的下一个项目中尝试它,因为我认为

meson
ninja
不适用于 C++ 模块。

使用声明创建

mylib.h
。使用模板定义创建一个
mylib_impl.h
。创建一个
mylib.cpp
... 并使其包含
mylib_impl.h
并为最常用的类型进行显式实例化。

请注意,

mylib_impl.h
将会
#include "mylib.h"
。但
mylib.h
末尾不会包含
mylib_impl.h

现在,大多数人都会包括

mylib.h
。如果该用户碰巧需要一些“非标准”类型,则用户必须包含
mylib_impl.h
或将此新实例添加到
mylib.cpp

可能需要教育用户很少使用

mylib_impl.h
。文档很重要,因为包含
mylib_impl.h
永远不会导致链接器错误,而
mylib.h
可能会导致链接器错误。

此外,还必须链接到

mylib.cpp

最后,如果我说了什么蠢话,我很抱歉。请耐心等待。 :-)

© www.soinside.com 2019 - 2024. All rights reserved.