一、模块
在非c/c++语言中,引入其它的类似库的文件,一般都是使用import某某包,像JAVA,GOLANG,PYTHON等,这样的优势在于,简单明了,不容易产生循环引用,即使产生后也容易发现和解决。回过头来再看c++和C中,对头文件的要求可是非常的严格,首先是顺序,比如先引用哪个再引用哪个;然后是对循环依赖的解决。可能有的人反对说不难啊。确实,中小型文件确实是比较好解决,工程稍微大一些,就会发现,经常会出现一些莫名其妙的事情,找来找去,发现最后竟然是头文件的问题。
这也是c++饱受争议的地方,不过这在c++20得到了改善,出现了module这个概念,也开始和其它语言一样,import 和export了。下面就看看这位大哥是何方神圣,如何使用。
二、应用
在VS2019(在前面提到过一般使用GCC,可这次GCC真得有点慢,只好用VS2019)中,按支持C++20的配置(见协程一文)生成各种支持配置。注意,这只是第一步,下一步就是要处理一下对module的支持,总体上来说,目前用起来还是以尝鲜为主,真正用到工程上就别想了。不过估计下一个版本的VC,会支持的不错。
启动VS2019创建一个控制台程序,为了简单只写了三个文件,即test.cpp,mymu.cpp这两个module文件,一个自动生成的主文件。内容如下:
//main.cpp
import std.core;
import mymu;
import test;
using namespace mymu;
void TestSTL()
{
std::vector<int> vec;
vec.resize(10);
vec[0] = 100;
std::cout << "this is test STL!" <<"vector first value:"<<vec[0]<< std::endl;
}
int main()
{
TestSTL();
//此处有一个小瑕疵,在前面已经引用了mymu名空间,原则上可以不使用限定符
//可惜调用的函数和另外一个名空间名字冲突,编译无法通过,只好加上
int d = mymu::test(100);
d = test::mytest(1,300);
std::cout << "max value is:"<<d<<std::endl;
}
//mymu.cpp
module mymu;
namespace mymu {
int test(int a)
{
return a+a + a;
}
}
//test.cpp
module test;
namespace test
{
int mytest(int a, int b)
{
return a * b;
}
}
启动编译,会发现报不少错,找不到这个模块那个模块,因此好多函数调用也找不到。这就需要再增加处理的一步:
从相关资料中找到写的批处理文件,内容根据实际情况修改:
rem set mycl=D:\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.27.29110\bin\Hostx64\x64
set mycl=cl.exe
rem /experimental:module /module:stdIfcDir "$(VCToolsInstallDir_160)ifc\$(PlatformTarget)"
rem $(VCToolsInstallDir_160)=D:\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.27.29110\
rem $(PlatformTarget)=x64
set target=%1%
if "%target%"=="" set target=x64
@echo %target%
set stdIfcDir="D:\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.27.29110\ifc\%target%"
set rundll=%2%
if "%rundll%"=="" set rundll=MD
@echo %rundll%
set CFLAGS=/experimental:module /std:c++latest /EHsc /%rundll% /c /module:stdIfcDir %stdIfcDir% /module:export
rem cl.exe /experimental:module /std:c++latest /EHsc /MD /c /module:stdIfcDir "D:\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.27.29110\ifc\x64" /module:export mymu.cpp
"%mycl%" %CFLAGS% mymu.cpp
"%mycl%" %CFLAGS% test.cpp
保存为.bat文件,看到内容就可以明白,其中的文件是和上面生成的控制台项目中的文件相对应,这里面写得比较简,没有对类或者对空间中的某个函数函数的导出,其实在模块中都是支持的,这个好像有点把头文件和动态库合二为一的样子。
再次启动编译,会报一大堆的警告,不用管他,然后就可以运行出结果了。缺点是,每增加一个模块,都得在批处理文件中增加一个处理项,麻烦。算是一次预演吧。
三、总结
新功能确实让人向往,而且c++的受关注程序开始大幅回升,可能和新标准的不断迭代有相当关系,还要继续努力!