C++20模块

  • Post author:
  • Post category:其他


C++20的模块,高封装性,单次定义规则,是一项比较新的技术,我总结了一些规律,现记录下来。

我在VS2022中编写模块文件,需要开启C++20支持,模块的扩展文件是 .ixx 这种文件被自动识别为模块文件。

Module.ixx

module;
#include<iostream>
#include<cstdlib>
#include<thread>
#include<experimental/coroutine>
#include<ranges>
#include<vector>
#include<atomic>
#include<memory>
#include<functional>
export module Module;
import string;
import thread;

class Point {
	//inline static const std::vector<int> arr = { 12,34,56,78,89,56,5634,534,56 };
public:
	constexpr Point() {  }
	auto operator <=>(const Point& value) const = default;
	consteval auto GetX() const {
		// ....................
	}
	constexpr auto GetArr() const {
		// .............
…

上面的这个示例呢,最开始的module表示一个全局模块的开始,由这个关键字开始的在其后面可以编写预处理器定义,再往下看,就是export module Module;这里就是我导出了一个全局模块,这个模块的名字叫Module,它可以被外部进行引入。下方的import string;就是我在其他的.ixx文件中导出的模块。

在模块导出时,我需要指定哪些需要被导出,对于我想要导出的类型,我可以在我的类型前面加入export

module;
export module string;
export class MyString final {
public:
	static wchar_t* CharToWchar(const char* v1, wchar_t*& v2);

	static char* WcharToChar(const wchar_t* v1, char*& v2);

	static wchar_t* Utf8ToWchar(const char* v1, wchar_t*& v2);

	static char* WcharToUtf8(const wchar_t* v1, char*& v2);
};


我在string模块中导出了一个类(MyString)。


如果你在阅读这个文章,你可能发现了不同处,上面的类只有声明,没有定义,是的!他的定义在其他的模块文件中。我将他的定义放在了模块string.core.ixx文件中,

module;
#include<Windows.h>
#include<assert.h>
module string;        // 作为主模块的分区实现文件,可在其他分区使用。
class MyString
{
public:
	static wchar_t* CharToWchar(const char* v1, wchar_t*& v2) {
		assert(v1 != NULL);
		if (v2 != nullptr) Free(v2);
		int len = MultiByteToWideChar(CP_ACP, 0, v1, -1, NULL, 0);
		v2 = new wchar_t[len];
		MultiByteToWideChar(CP_ACP, 0, v1, (int)strlen(v1), v2, len);
		v2[len - 1] = L'\0';
		return v2;
	}
………其他代码实现省略。


当我在写某一个模块的定义文件时,这就叫模块的分区文件,他作为string模块的分区实现文件,在开头预处理指令结束后,就需要声明模块,module string; 在编写定义的代码是,无需再次进行export,按照正常的逻辑编写即可,这个模块不需要导出,也不需要在其他的模块导入(私有模块);


如果我想要在其他的分区共享模块的分区文件,那么我可以这样编写:


export


module


MyModule:String;


//


作为主模块的分区实现文件,可在其他分区使用。

我在MyModule写定义,在String写实现,并且导出这个String模块分区,既然导出了,那么我就可以导入了,我在其他的模块分区想使用他,于是我编写了这个代码:


import


:String;


//


导入分区模块,分区实现文件可见。

前缀以冒号开头,表示一个分区模块。

在我编写这个文档的时候,模块技术还不是很成熟,标准库的模块支持,这个可以在项目属性中修改,以增加对模块标准库的访问:

以下示例是引用的标准库模块,有可能需要下载单个组件,支持模块标准库。

import MyModule;
#pragma warning(disable:5050)     // 解除标准库模块头文件的警告。

import std.core;
int main()
{
    std::cout << "hello,word" << std::endl;
    return 0;
}



版权声明:本文为weixin_42951026原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。