概念

现在模块化编程,替代头文件,解决模块间符号可见性控制问题

模块声明

编译单元默认普通单元module关键字模块单元export module定义模块对外接口

export module helloworld;
//符号默认对模块外不可见
void private_hello() {
    std::cout << "Hello World!" << std::endl;
}
//定义外部可见函数
export void hello() {
    private_hello():
}
//导出整个namespace,不推荐
export namespace hname {
    int get_num() {
        return 0;
    }
}
//推荐namespace内细粒度控制
namespace xname {
    export int get_num() {
        return 0;
    }
}

导入模块

import关键字导入模块,让被引用模块的符号在本编译单元可见,类似using namespace,可以用export import将导入符号对外导出

///bye.cpp
export module bye;
import <iostream>
export void goodbye() {
    std::cout << "Goodbye" << std::endl;
}

///helloworld.cpp
export module helloworld;
export import bye;
export void hello() {
    std::cout << "Hello World!" << std::endl;
}

///main.cpp
import helloworld;
int main() {
    helloe();
    goodbye();
    return 0;
}

导入头文件

importinclude区别是,通过impor导入头文件的编译单元定义的预处理宏,是无法被import导入的文件访问的,可以用模块片段来实现使用预处理宏影响头文件

全局模块片段

module;
//预处理宏指令
//模块声明

模块分区

模块的一个关键特性是可以划分为更多的子模块。在 C++ Modules 中,子模块主要有两种实现方式:通过模块名称进行区分(utils.image)、利用模块分区特性(模块名:分区名)。

//helloworld_a.cpp
export module helloworld:A;

//helloworld_b.cpp
export module helloworld:B

//helloworld.cpp
export module helloworld;
export import :A;
import :B;

模块所有权

使用模块的时候需要注意符号声明的所有权问题,这影响符号的实现位置和符号的链接性(linkage)

export module lib;
namespace hello { //命名空间不属于lib
    extern "C++" int32_t f(); //外部链接c++方式符号,不属于lib
    extern "C" int32_t g(); //外部链接c方式符号,不属于lib
    int32_t x(); //hello::x属于lib,只能被同模块编译单元使用
    export int32_t z(); //hello::z属于lib,可被其它模块编译单元使用
}

乌托邦

xl

Stay hungry, Stay foolish.