c++ - 如何在 C++20 模块中使用模板显式实例化?

标签 c++ templates c++20 c++-modules

如解释 in this answer模板实例化允许通过不需要为使用它们的每个新文件中的每个新类型重新编译模板来减少编译时间和大小。

我也很兴奋 C++20 modules应该提供一个干净的解决方案来向外部项目公开模板并减少 hpp/cpp 重复。

允许它们一起工作的语法是什么?

例如,我希望模块看起来有点像(未经测试,因此可能是错误的代码,因为我没有足够新的编译器/不确定它是否已实现):

Hello World .cpp

export module helloworld;
import <iostream>;

template<class T>
export void hello(T t) {
    std::cout << t << std::end;
}

helloworld_impl.cpp
export module helloworld_impl;
import helloworld;

// Explicit instantiation
template class hello<int>;

主文件
// How to prevent the full definition from being imported here, which would lead
// hello(1) to instantiate a new `hello<int>` instead of reusing the explicit instantiated
// one from `helloworld_impl.cpp`?
import helloworld;

int main() {
    hello(1);
}

然后在 https://quuxplusone.github.io/blog/2019/11/07/modular-hello-world 中提到的编译将伴随(?)
clang++ -std=c++2a -c helloworld.cpp -Xclang -emit-module-interface -o helloworld.pcm
clang++ -std=c++2a -c -fprebuilt-module-path=. -o helloworld_impl.o helloworld_impl.cpp
clang++ -std=c++2a -fprebuilt-module-path=. -o main.out main.cpp helloworld_impl.o

理想情况下,我还希望模板定义可用于外部项目。

我想我想要的是一种导入模块的方法,并在导入时决定:
  • 使用模块中的所有模板,就好像它们只是声明一样(我将在另一个文件中提供我自己的实例化)
  • 使用模块中的模板,就好像它们是定义

  • 这基本上是我在 C++20 之前的 "Remove definitions from included headers but also expose templates an external API" 中实现的。但是该设置需要复制接口(interface)两次,这似乎是模块系统基本上可以为我们做的事情。

    最佳答案

    模块使“快速单一构建”案例变得非常容易。它们对于“支持客户端实例化但避免重建显式实例化特化的客户端”的情况并没有做太多;该理论认为,避免重复工作通常更快的构建使得无需扭曲程序以节省更多时间。

    您所做的只是放置一个显式实例化 定义 在模块界面中:

    export module A;
    export template<class T>
    inline void f(T &t) {++t;}
    template void f(int&);
    template void f(int*&);
    

    进口商不必实例化 f对于这两种类型中的任何一种,即使函数模板是 内联 (这可能需要在非模块化代码中进行额外的实例化)。典型的实现将这些实例化的结果缓存在已编译的模块接口(interface)文件中,并具有足够的细节以在导入器中内联调用(以及缓存模板本身的足够细节以进一步实例化它)。

    您当然也可以使用显式实例化 声明 只需在接口(interface)中声明模板并定义模板并将显式实例化定义放在模块实现单元中,但这与头文件的工作方式没有什么不同。

    关于c++ - 如何在 C++20 模块中使用模板显式实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61520847/

    相关文章:

    c++ - 为什么 std::vector 调整大小失败?

    c++ - 打开PostgreSQL数据库连接的效率

    c++ - 使用体素几何体进行光照贴图

    c++ - 从类模板派生的类的通用函数

    c++ - 覆盖语法,返回指向固定大小数组的指针的专用模板方法

    c++ - 继承基类的所有内容

    c++ - 授予模板类特化的构造函数/析构函数友好 - 在 C++17 下工作,但在 C++20 下失败

    c++ - 为什么 range-v3 中不能对范围进行排序?

    c++ - 在全局 fixture 中使用系统 boost UTF

    c++ - 在封闭对象的生命周期内通过 placement new 重用数据成员存储