Modules是C++ 20标准里面一个非常重要的新特性,一个模块的所有接口文件、实现文件,作为一个翻译单元,一次编译后生成 pcm,之后遇到 Import 该模块的代码,编译器会从 pcm 中寻找函数声明等信息,该特性会极大加快 C++ 代码的编译速度。
以《C++高级编程》第五版中第一章中25_ConstAirlineTicket源码为例,体验下将Header Files改变为Module Interface Files的过程,注意module、export、import等关键字。
A C++ module interface unit with an interface only AirlineTicket.cppm:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 module ;import <string>;export module airline_ticket;export class AirlineTicket { public : double calculatePriceInDollars () const ; std::string getPassengerName () const ; void setPassengerName (std::string name) ; int getNumberOfMiles () const ; void setNumberOfMiles (int miles) ; bool getHasEliteSuperRewardsStatus () const ; void setHasEliteSuperRewardsStatus (bool status) ; private : std::string m_passengerName{ "Unknown Passenger" }; int m_numberOfMiles{ 0 }; bool m_hasEliteSuperRewardsStatus{ false }; };
A C++ module implementation unit AirlineTicket.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 module airline_ticket;import <string>;using namespace std;double AirlineTicket::calculatePriceInDollars () const { if (getHasEliteSuperRewardsStatus ()) { return 0 ; } return getNumberOfMiles () * 0.1 ; } std::string AirlineTicket::getPassengerName () const { return m_passengerName; } void AirlineTicket::setPassengerName (string name) { m_passengerName = name; } int AirlineTicket::getNumberOfMiles () const { return m_numberOfMiles; } void AirlineTicket::setNumberOfMiles (int miles) { m_numberOfMiles = miles; } bool AirlineTicket::getHasEliteSuperRewardsStatus () const { return m_hasEliteSuperRewardsStatus; } void AirlineTicket::setHasEliteSuperRewardsStatus (bool status) { m_hasEliteSuperRewardsStatus = status; }
Programs that import modules AirlineTicketTest.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import <iostream>;import airline_ticket;#include <fmt/format.h> using namespace std;int main () { AirlineTicket myTicket; myTicket.setPassengerName ("Sherman T. Socketwrench" ); myTicket.setNumberOfMiles (700 ); double cost{ myTicket.calculatePriceInDollars () }; std::cout << fmt::format("This ticket will cost ${}" , cost) << std::endl; }
C++编译器方面,目前MSVC对C++20支持最齐全,其次是GCC、Clang,而GCC和Clang在Module编译命令有些不同,以Clang为例,编写对应的CMake编译文件如下:
CMakeLists.txt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 cmake_minimum_required (VERSION 3.16 )set (CMAKE_C_COMPILER /usr/bin/clang)set (CMAKE_CXX_COMPILER /usr/bin/clang++)set (CMAKE_CXX_FLAGS " -Wall -Werror -O3 -DNDEBUG " )set (CMAKE_EXE_LINKER_FLAGS " -lc++ -lc++abi " )project (25 _ConstAirlineTicket)find_package (fmt)set (CMAKE_CXX_STANDARD 20 )set (CMAKE_CXX_STANDARD_REQUIRED ON )set (CMAKE_CXX_EXTENSIONS OFF )set (PREBUILT_MODULE_PATH ${CMAKE_BINARY_DIR} /modules)function (add_module name) file (MAKE_DIRECTORY ${PREBUILT_MODULE_PATH} ) add_custom_target (${name} .pcm COMMAND ${CMAKE_CXX_COMPILER} -std=c++20 -stdlib=libc++ -fmodules -x c++ -c ${CMAKE_CURRENT_SOURCE_DIR} /${ARGN} -Xclang -emit-module-interface -o ${PREBUILT_MODULE_PATH} /${name} .pcm ) endfunction ()add_module(AirlineTicket AirlineTicket.cppm) add_compile_options (-stdlib=libc++)add_compile_options (-fmodules)add_compile_options (-fbuiltin-module-map)add_compile_options (-fimplicit-module-maps)add_compile_options (-fmodule-file =${PREBUILT_MODULE_PATH} /AirlineTicket.pcm)set (TARGET main)set (SOURCES AirlineTicket.cpp AirlineTicketTest.cpp)add_executable (${TARGET} ${SOURCES} )add_dependencies (${TARGET} AirlineTicket.pcm)target_link_libraries (${TARGET} PRIVATE fmt::fmt-header-only)
在源码文件夹中,新建build文件夹,进入build后终端上执行cmake .. && make 。
本文链接: https://azurelake.cn/posts/985d772f38eb/
版权声明: 转载请注明出处(必须保留作者署名及链接)