设为首页 加入收藏

TOP

C++20 的 Modules(一)
2019-07-12 18:10:50 】 浏览:113
Tags:Modules

最近看了两篇关于 C++ 20 Modules 很有意思的文章,戳:

《Understanding C++ Modules: Part 1: Hello Modules, and Module Units》

《Understanding C++ Modules: Part 2: export, import, visible, and reachable》

众所周知,C++靠预处理器处理头文件的方法被诟病已久。在 C++17 Module TS 后,标准委员会的 dalao 们终于在 C++20Modules 并入标准= =。(此处应该有掌声?

那么我们要怎么创建一个 Module 呢?标准引入了新的关键字 importmodule,并使用保留关键字 export 来导入、定义和导出 Module。

// hello_world.cpp
export module demos.hello.world;

export auto get_text()
{
  return "Hello C++ Modules!";
}
// main.cpp
import demos.hello.world;
import <iostream>;

int main()
{
  std::cout << get_text() << std::endl;
}

这是一个 C++20 Modules 版的 Hello World。注意 export module xxx.yyy.zzz 是一个 Module 的导出定义,函数 get_text 加上 export 就成为 Module 的导出符号。

Module 的名字可以是 aaa.bbb.ccc.ddd 这样的,此处借鉴了其他语言的命名规范,提升了可读性。

根据标准,每个 Module 都是一个 TU(Translation Unit) ,这样就可以在构建时得到更好的 Cache 编译的效果,缩短编译时间。

最后说下 import <iostream> 这样的用法。这是为了兼容以前老的头文件的写法,意思是把一个头文件当作一个独立的 TU 来编译,并且避免了命名空间污染和主文件中符号的影响。

-------------华丽分割线1--------------

一些语言,如 C# 有 partial class 的语法,可以把一个完整的 class 拆分为多个文件,最后合并编译。C++ Modules 提供了一个特性叫 Module Partition,可以把 Module 拆分在多个 .cpp 文件中定义。

在标准中,使用 Module 名称 + 冒号 + Partition 名称 的方式来定义一个 Module Partition

// home.cpp
export module home;
export import :father;
export import :mother;
// home_father.cpp
export module home:father;

export auto get_father_name()
{
  return "Xiaoming";
}
// home_mother.cpp
export module home:mother;

export auto get_mother_name()
{
  return "Xiaohong";
}
// main.cpp
import home;

int main()
{
  auto father = get_father_name();
  auto mother = get_mother_name();
}

这样 fathermother 就成为 Module home 的两个 Partition。吐槽一下 export import :xxx 这种语法,它的意思是把 Partition 先 import 进来再 re-export 出去,让用户可见。

这里多了一个概念:Module Interface Unit。很 Simple,对于一个 .cpp 文件,如果是 export module xxx 这样的,就是一个 Module Interface Unit,意思是导出接口单元。

比如上面的 home.cpp, home_father.cpp 和 home_mother.cpp 都是 Module Interface Unit

-------------华丽分割线2--------------

除了 Module Interface Unit,还有一个对应的东西叫 Module Implementation Unit ,模块实现单元。

同样很 Easy,如果一个 .cpp 文件中定义的是 module xxx,注意前面没有 export ,那么它就是一个 Module Implementation Unit

// animal.cpp
export module animal;
import :dogs;
import :cats;

export auto get_cat_name();
export auto get_dog_name();
// animal_cats.cpp
module animal:cats;

// "export" is not allowed here.
auto get_cat_name()
{
  return "狗·德川家康·薛定鄂·保留";
}
// animal_dogs.cpp
module animal:dogs;

// "export" is not allowed here.
auto get_cat_name()
{
  return "DOGE";
}
// main.cpp
import animal;

int main()
{
  auto cat_name = get_cat_name();
  auto dog_name = get_dog_name();
}

Partition catsdogs 就是两个 Module Implementation Unit ,而 animal.cpp 是一个 Module Interface Unit

注意 Implementation Unit 里面不允许有 export 出现,且需要在 Interface Unit 中 import 对应的 Partition。

想偷懒?同志好想法,还有种不需要 Partition 的简化写法。

// animal.cpp
export module animal;

export auto get_cat_name();
export auto get_dog_name();
// animal_impl.cpp
module animal;

auto get_cat_name()
{
  return "狗·德川家康·薛定鄂·保留";
}

auto get_cat_name()
{
  return "DOGE";
}

是不是感觉似曾相识?这个和目前的老式头文件声明和定义分离的用法如出一辙。

animal_impl.cpp 定义的还是叫 Module Implementation Unit ,animal.cpp 叫 Module Interface Unit

WHY? 既然可以写在一起,为什么要分离呢。一个是满足代码习惯,还有一个就是如果频繁修改实现,可以不动接口,提高

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇洛谷 P3373 【模板】线段树 2 下一篇HelloWorld! C++纠错版

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目