├── 13 ├── include │ ├── ca │ │ ├── IoUtils.h │ │ ├── RangeUtils.h │ │ ├── TimeUtils.h │ │ ├── Types.h │ │ └── algorithms │ │ │ ├── FunctionalAlgorithm.h │ │ │ ├── ProcedureAlgorithm.h │ │ │ └── RangesAlgorithm.h │ └── data.h └── src │ ├── ca │ ├── IoUtils.cpp │ ├── TimeUtils.cpp │ └── algorithms │ │ ├── FunctionalAlgorithm.cpp │ │ ├── ProcedureAlgorithm.cpp │ │ └── RangesAlgorithm.cpp │ ├── data.cpp │ └── main.cpp ├── 14 ├── CMakeLists.txt └── Projects │ ├── 01-SimpleLog │ └── src │ │ └── main.cpp │ ├── 02-FormatTo │ └── src │ │ └── main.cpp │ ├── 03-VFormat │ └── src │ │ └── main.cpp │ └── 04-Formatter │ └── src │ └── main.cpp ├── 15 ├── CMakeLists.txt └── Projects │ ├── logger │ ├── include │ │ └── logging │ │ │ ├── Formatter.h │ │ │ ├── Handler.h │ │ │ ├── Level.h │ │ │ ├── Logger.h │ │ │ ├── Record.h │ │ │ ├── formatters │ │ │ ├── CFormatter.h │ │ │ ├── ModernFormatter.h │ │ │ └── StreamFormatter.h │ │ │ └── handlers │ │ │ ├── DefaultHandler.h │ │ │ ├── FileHandler.h │ │ │ └── StreamHandler.h │ └── src │ │ └── logging │ │ └── formatters │ │ ├── CFormatter.cpp │ │ ├── ModernFormatter.cpp │ │ └── StreamFormatter.cpp │ └── sample │ └── src │ └── main.cpp ├── 18 ├── CMakeLists.txt └── Projects │ ├── 01-JThreadSample │ └── src │ │ └── main.cpp │ ├── 01-OldBit │ └── src │ │ └── main.cpp │ ├── 02-SourceLocation │ └── src │ │ └── main.cpp │ ├── 03-Calendar │ └── src │ │ └── main.cpp │ ├── 04-Timezone │ └── src │ │ └── main.cpp │ ├── 05-SyncStream │ └── src │ │ └── main.cpp │ ├── 06-U8String │ └── src │ │ └── main.cpp │ └── 07-WindowsThread │ └── src │ └── main.cpp ├── 19 ├── CMakeLists.txt └── Projects │ ├── calendar │ ├── include │ │ ├── Logger.h │ │ ├── actions │ │ │ ├── ExitAction.h │ │ │ ├── ExportAction.h │ │ │ └── ShowAction.h │ │ ├── menu │ │ │ └── Menu.h │ │ └── utils │ │ │ ├── CalendarUtils.h │ │ │ ├── IOUtils.h │ │ │ └── RenderUtils.h │ └── src │ │ ├── Logger.cpp │ │ ├── actions │ │ ├── ExitAction.cpp │ │ ├── ExportAction.cpp │ │ └── ShowAction.cpp │ │ ├── main.cpp │ │ ├── menu │ │ └── Menu.cpp │ │ └── utils │ │ ├── CalendarUtils.cpp │ │ ├── IOUtils.cpp │ │ └── RenderUtils.cpp │ └── logger │ ├── include │ └── logging │ │ ├── Formatter.h │ │ ├── Handler.h │ │ ├── Level.h │ │ ├── Logger.h │ │ ├── Record.h │ │ ├── formatters │ │ ├── CFormatter.h │ │ ├── ModernFormatter.h │ │ └── StreamFormatter.h │ │ └── handlers │ │ ├── DefaultHandler.h │ │ ├── FileHandler.h │ │ └── StreamHandler.h │ └── src │ └── logging │ └── formatters │ ├── CFormatter.cpp │ ├── ModernFormatter.cpp │ └── StreamFormatter.cpp ├── 01 ├── CMakeLists.txt └── src │ ├── v1 │ ├── a.cpp │ └── b.cpp │ ├── v2 │ ├── a.cpp │ ├── b.cpp │ └── b.h │ └── v3 │ ├── a.cpp │ ├── b.cpp │ └── b.h ├── 02 ├── 01-ModuleGettingStarted │ ├── CMakeLists.txt │ └── src │ │ ├── helloworld.cpp │ │ ├── helloworld.ixx │ │ └── main.cpp ├── 02-MultiModules │ ├── CMakeLists.txt │ └── src │ │ ├── bye.cpp │ │ ├── bye.ixx │ │ ├── helloworld.cpp │ │ ├── helloworld.ixx │ │ └── main.cpp ├── 03-ModuleInclude │ ├── CMakeLists.txt │ └── src │ │ ├── h1.h │ │ ├── h2.h │ │ ├── helloworld.cpp │ │ ├── helloworld.ixx │ │ └── main.cpp ├── 04-GlobalModuleFragment │ ├── CMakeLists.txt │ └── src │ │ ├── h2.h │ │ ├── helloworld.cpp │ │ ├── helloworld.ixx │ │ └── main.cpp ├── 05-PrivateModuleFragment │ ├── CMakeLists.txt │ └── src │ │ ├── h2.h │ │ ├── helloworld.cpp │ │ ├── helloworld.ixx │ │ └── main.cpp └── 06-ModulePartition │ ├── CMakeLists.txt │ └── src │ ├── helloworld.cpp │ ├── helloworld.ixx │ ├── helloworldA.cpp │ ├── helloworldA.ixx │ ├── helloworldB.cpp │ ├── helloworldB.ixx │ └── main.cpp ├── 03 ├── CMakeLists.txt └── src │ ├── app │ ├── app.cpp │ └── app.ixx │ ├── cache │ ├── cache.cpp │ ├── cache.ixx │ ├── loader.cpp │ └── loader.ixx │ ├── command │ ├── argument.cpp │ ├── argument.ixx │ ├── command.cpp │ ├── command.ixx │ ├── parser.cpp │ └── parser.ixx │ ├── image │ ├── image.cpp │ ├── image.ixx │ ├── processor.cpp │ └── processor.ixx │ ├── main.cpp │ └── network │ ├── connection.cpp │ ├── connection.ixx │ ├── network.cpp │ ├── network.ixx │ ├── request.cpp │ ├── request.ixx │ ├── response.cpp │ ├── response.ixx │ ├── server.cpp │ └── server.ixx ├── 04 ├── 01-BasicTemplate │ ├── CMakeLists.txt │ └── src │ │ ├── c11.cpp │ │ ├── c11.h │ │ └── main.cpp ├── 02-Specializations │ ├── CMakeLists.txt │ └── src │ │ ├── c13.h │ │ └── main.cpp ├── 03-ParamterPack │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 04-TypeTraits │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp └── 05-ErrorMessage │ ├── CMakeLists.txt │ └── src │ └── main.cpp ├── 05 ├── 01-BasicConcepts │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 02-Conjunctions │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 03-Disjunctions │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 04-AutomicConstraints │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 05-RequiresExpressions │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp └── 06-RequiresClauses │ ├── CMakeLists.txt │ └── src │ └── main.cpp ├── 06 └── NumCpp │ ├── CMakeLists.txt │ └── src │ ├── main.cpp │ └── numcpp │ ├── algorithm │ ├── aggregate.cpp │ ├── aggregate.ixx │ ├── algorithm.cpp │ ├── algorithm.ixx │ ├── basic.cpp │ ├── basic.ixx │ ├── universal.cpp │ └── universal.ixx │ ├── array.cpp │ ├── array.ixx │ ├── array_view.cpp │ ├── array_view.ixx │ ├── concepts.cpp │ ├── concepts.ixx │ ├── creation.cpp │ ├── creation.ixx │ ├── numcpp.cpp │ ├── numcpp.ixx │ ├── types.cpp │ ├── types.ixx │ ├── utils.cpp │ └── utils.ixx ├── 07 ├── 01-BasicThread │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 02-BasicFileSystem │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp └── 03-FutureFileSystem │ ├── CMakeLists.txt │ └── src │ └── main.cpp ├── 08 ├── 01-PromiseType │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 02-CoroutineHandle │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp ├── 03-Generator │ ├── CMakeLists.txt │ └── src │ │ └── main.cpp └── 04-Concepts │ └── src │ └── main.cpp ├── 09_and_10 └── Asyncpp │ ├── CMakeLists.txt │ └── src │ ├── core │ ├── Concepts.cpp │ ├── Concepts.ixx │ ├── Core.cpp │ └── Core.ixx │ ├── fs │ ├── FileSystem.cpp │ └── FileSystem.ixx │ ├── io │ ├── AsyncIoAsyncify.cpp │ ├── AsyncIoAsyncify.ixx │ ├── AsyncIoLoop.cpp │ ├── AsyncIoLoop.ixx │ ├── AsyncIoTask.cpp │ ├── AsyncIoTask.ixx │ ├── Io.cpp │ └── Io.ixx │ ├── main.cpp │ └── task │ ├── AsyncTaskLoop.cpp │ ├── AsyncTaskLoop.ixx │ ├── AsyncTaskQueue.cpp │ ├── AsyncTaskQueue.ixx │ ├── Asyncify.cpp │ ├── Asyncify.ixx │ ├── Coroutine.cpp │ ├── Coroutine.ixx │ ├── Task.cpp │ └── Task.ixx ├── 11_and_12 ├── CMakeLists.txt └── Projects │ ├── 01-STLSample │ └── src │ │ └── main.cpp │ ├── 02-RangesSample │ └── src │ │ └── main.cpp │ ├── 03-RangesIteratorSample │ └── src │ │ └── main.cpp │ ├── 04-RangesSizeSample │ └── src │ │ └── main.cpp │ ├── 05-RangesDataSample │ └── src │ │ └── main.cpp │ ├── 06-RangesDanglingFailed │ └── src │ │ └── main.cpp │ ├── 07-RangesDanglingCheck │ └── src │ │ └── main.cpp │ ├── 08-ViewBasic │ └── src │ │ └── main.cpp │ ├── 09-ArrayView │ └── src │ │ └── main.cpp │ ├── 10-FactorySample │ └── src │ │ └── main.cpp │ ├── 11-AdaptorSample │ └── src │ │ └── main.cpp │ ├── 12-STLRandom │ └── src │ │ └── main.cpp │ └── 13-PipelineSample │ └── src │ └── main.cpp ├── 16_and_17 ├── CMakeLists.txt ├── CMakeSettings.json └── Projects │ ├── 01-OldBit │ └── src │ │ └── main.cpp │ ├── 02-EndianProcess │ └── src │ │ └── main.cpp │ ├── 03-BitCast │ └── src │ │ └── main.cpp │ ├── 04-BitRotating │ └── src │ │ └── main.cpp │ ├── 05-OtherBit │ └── src │ │ └── main.cpp │ └── 06-DataStream │ ├── include │ ├── ca │ │ ├── BitCompact.h │ │ ├── BitUtils.h │ │ ├── IoUtils.h │ │ ├── RangeUtils.h │ │ ├── SerializeUtils.h │ │ ├── TimeUtils.h │ │ ├── Types.h │ │ └── algorithms │ │ │ ├── FunctionalAlgorithm.h │ │ │ ├── ProcedureAlgorithm.h │ │ │ └── RangesAlgorithm.h │ └── data.h │ └── src │ ├── ca │ ├── IoUtils.cpp │ ├── SerializeUtils.cpp │ ├── TimeUtils.cpp │ └── algorithms │ │ ├── FunctionalAlgorithm.cpp │ │ ├── ProcedureAlgorithm.cpp │ │ └── RangesAlgorithm.cpp │ ├── data.cpp │ └── main.cpp ├── README.md ├── cpp20-plus-and-evermore.png └── mid_term_exam_sol ├── .vscode └── settings.json ├── CMakeLists.txt └── src ├── core ├── Concepts.cpp ├── Concepts.ixx ├── Core.cpp └── Core.ixx ├── fs ├── FileSystem.cpp └── FileSystem.ixx ├── hp ├── AsyncHpLoop.ixx ├── AsyncHpTask.ixx └── Hp.ixx ├── io ├── AsyncIoAsyncify.cpp ├── AsyncIoAsyncify.ixx ├── AsyncIoLoop.cpp ├── AsyncIoLoop.ixx ├── AsyncIoTask.cpp ├── AsyncIoTask.ixx ├── Io.cpp └── Io.ixx ├── main.cpp └── task ├── AsyncTaskLoop.cpp ├── AsyncTaskLoop.ixx ├── AsyncTaskQueue.cpp ├── AsyncTaskQueue.ixx ├── Asyncify.cpp ├── Asyncify.ixx ├── Coroutine.cpp ├── Coroutine.ixx ├── Task.cpp └── Task.ixx /01/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch01) 4 | 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | add_executable( 9 | MyAppV1 10 | src/v1/a.cpp 11 | src/v1/b.cpp 12 | ) 13 | 14 | add_executable( 15 | MyAppV2 16 | src/v2/a.cpp 17 | src/v2/b.cpp 18 | ) 19 | target_include_directories( 20 | MyAppV2 21 | PRIVATE 22 | src/v2 23 | ) 24 | target_sources( 25 | MyAppV2 26 | PRIVATE 27 | src/v2/b.h 28 | ) 29 | 30 | add_executable( 31 | MyAppV3 32 | src/v3/a.cpp 33 | src/v3/b.cpp 34 | ) 35 | target_include_directories( 36 | MyAppV3 37 | PRIVATE 38 | src/v3 39 | ) 40 | target_sources( 41 | MyAppV3 42 | PRIVATE 43 | src/v3/b.h 44 | ) 45 | -------------------------------------------------------------------------------- /01/src/v1/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern int32_t add(int32_t a, int32_t b); 5 | 6 | int main() { 7 | int32_t sum = add(1, 2); 8 | std::cout << "sum: " << sum << std::endl; 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /01/src/v1/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int32_t add(int32_t a, int32_t b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /01/src/v2/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "b.h" 4 | 5 | int main() { 6 | int32_t sum = add(1, 2); 7 | std::cout << "sum: " << sum << std::endl; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /01/src/v2/b.cpp: -------------------------------------------------------------------------------- 1 | #include "b.h" 2 | 3 | int32_t add(int32_t a, int32_t b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /01/src/v2/b.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_B_H 2 | #define _MODULE_B_H 3 | 4 | #include 5 | 6 | extern int32_t add(int32_t a, int32_t b); 7 | 8 | #endif //_MODULE_B_H 9 | -------------------------------------------------------------------------------- /01/src/v3/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "b.h" 4 | 5 | int32_t add(int32_t a, int32_t b) { 6 | return a + b; 7 | } 8 | 9 | int main() { 10 | int32_t sum = add(1, 2); 11 | std::cout << "sum: " << sum << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /01/src/v3/b.cpp: -------------------------------------------------------------------------------- 1 | #include "b.h" 2 | 3 | int32_t add(int32_t a, int32_t b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /01/src/v3/b.h: -------------------------------------------------------------------------------- 1 | #ifndef _MODULE_B_H 2 | #define _MODULE_B_H 3 | 4 | #include 5 | 6 | extern int32_t add(int32_t a, int32_t b); 7 | 8 | #endif //_MODULE_B_H 9 | -------------------------------------------------------------------------------- /02/01-ModuleGettingStarted/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 01-ModuleGettingStarted) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | 10 | function (prepare_for_module TGT) 11 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 12 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 13 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 14 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 15 | add_custom_target(std_modules ALL 16 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 17 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 18 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 19 | ) 20 | 21 | add_dependencies(${TGT} std_modules) 22 | endif() 23 | endfunction() 24 | 25 | set (MODULE_EXT cpp) 26 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 27 | set (MODULE_EXT ixx) 28 | endif() 29 | 30 | add_executable( 31 | ${TARGET} 32 | src/helloworld.${MODULE_EXT} 33 | src/main.cpp 34 | ) 35 | 36 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 37 | prepare_for_module(${TARGET}) 38 | endif() 39 | -------------------------------------------------------------------------------- /02/01-ModuleGettingStarted/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | import ; 5 | 6 | void private_hello() { 7 | std::cout << "Hello world!" << std::endl; 8 | } 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | } 13 | 14 | namespace hname { 15 | export int32_t getNumber() { 16 | return 10; 17 | } 18 | } -------------------------------------------------------------------------------- /02/01-ModuleGettingStarted/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | import ; 5 | 6 | void private_hello() { 7 | std::cout << "Hello world!" << std::endl; 8 | } 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | } 13 | 14 | namespace hname { 15 | export int32_t getNumber() { 16 | return 10; 17 | } 18 | } -------------------------------------------------------------------------------- /02/01-ModuleGettingStarted/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | import helloworld; 4 | 5 | int main() { 6 | hello(); 7 | std::cout << "Hello " << hname::getNumber() << std::endl; 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /02/02-MultiModules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 02-MultiModules) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | 10 | function (prepare_for_module TGT) 11 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 12 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 13 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 14 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 15 | add_custom_target(std_modules ALL 16 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 17 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 18 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 19 | ) 20 | 21 | add_dependencies(${TGT} std_modules) 22 | endif() 23 | endfunction() 24 | 25 | set (MODULE_EXT cpp) 26 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 27 | set (MODULE_EXT ixx) 28 | endif() 29 | 30 | add_executable( 31 | ${TARGET} 32 | src/bye.${MODULE_EXT} 33 | src/helloworld.${MODULE_EXT} 34 | src/main.cpp 35 | ) 36 | 37 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 38 | prepare_for_module(${TARGET}) 39 | endif() 40 | -------------------------------------------------------------------------------- /02/02-MultiModules/src/bye.cpp: -------------------------------------------------------------------------------- 1 | export module bye; 2 | 3 | import ; 4 | 5 | export void goodbye() { 6 | std::cout << "Goodbye" << std::endl; 7 | } -------------------------------------------------------------------------------- /02/02-MultiModules/src/bye.ixx: -------------------------------------------------------------------------------- 1 | export module bye; 2 | 3 | import ; 4 | 5 | export void goodbye() { 6 | std::cout << "Goodbye" << std::endl; 7 | } -------------------------------------------------------------------------------- /02/02-MultiModules/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | export import bye; 3 | 4 | import ; 5 | 6 | void private_hello() { 7 | std::cout << "Hello world!" << std::endl; 8 | } 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | } -------------------------------------------------------------------------------- /02/02-MultiModules/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | export import bye; 3 | 4 | import ; 5 | 6 | void private_hello() { 7 | std::cout << "Hello world!" << std::endl; 8 | } 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | } -------------------------------------------------------------------------------- /02/02-MultiModules/src/main.cpp: -------------------------------------------------------------------------------- 1 | import helloworld; 2 | 3 | int main() { 4 | hello(); 5 | goodbye(); 6 | 7 | return 0; 8 | } -------------------------------------------------------------------------------- /02/03-ModuleInclude/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 03-ModuleInclude) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | function (prepare_for_module TGT) 12 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 13 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 14 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 15 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 16 | add_custom_target(std_modules ALL 17 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 18 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 19 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 20 | ) 21 | 22 | add_custom_target(user_headers ALL 23 | COMMAND ${CMAKE_COMMAND} -E echo "Building Header caches" 24 | COMMAND g++ -fmodules-ts -std=c++20 ${CXX_SOURCE_DIR}/h1.h -c 25 | COMMAND g++ -fmodules-ts -std=c++20 ${CXX_SOURCE_DIR}/h2.h -c 26 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 27 | ) 28 | 29 | add_dependencies(${TGT} std_modules) 30 | add_dependencies(${TGT} user_headers) 31 | endif() 32 | endfunction() 33 | 34 | set (MODULE_EXT cpp) 35 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 36 | set (MODULE_EXT ixx) 37 | endif() 38 | 39 | add_executable( 40 | ${TARGET} 41 | src/helloworld.${MODULE_EXT} 42 | src/main.cpp 43 | ) 44 | target_include_directories( 45 | ${TARGET} 46 | PRIVATE 47 | src 48 | ) 49 | target_sources( 50 | ${TARGET} 51 | PRIVATE 52 | src/h1.h 53 | src/h2.h 54 | ) 55 | 56 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 57 | prepare_for_module(${TARGET}) 58 | endif() 59 | -------------------------------------------------------------------------------- /02/03-ModuleInclude/src/h1.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define H1 (1) -------------------------------------------------------------------------------- /02/03-ModuleInclude/src/h2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define H2 (H1 + 1) -------------------------------------------------------------------------------- /02/03-ModuleInclude/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | import "h1.h"; 5 | // #define H1 (1) 6 | import "h2.h"; 7 | 8 | export void hello() { 9 | std::cout << "Hello world!" << std::endl; 10 | std::cout << "Hello2 " << H1 << std::endl; 11 | std::cout << "Hello2 " << H2 << std::endl; 12 | } -------------------------------------------------------------------------------- /02/03-ModuleInclude/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | import "h1.h"; 5 | // #define H1 (1) 6 | import "h2.h"; 7 | 8 | export void hello() { 9 | std::cout << "Hello world!" << std::endl; 10 | std::cout << "Hello2 " << H1 << std::endl; 11 | std::cout << "Hello2 " << H2 << std::endl; 12 | } -------------------------------------------------------------------------------- /02/03-ModuleInclude/src/main.cpp: -------------------------------------------------------------------------------- 1 | import helloworld; 2 | 3 | int main() { 4 | hello(); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /02/04-GlobalModuleFragment/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 04-GlobalModuleFragment) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | function (prepare_for_module TGT) 12 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 13 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 14 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 15 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 16 | add_custom_target(std_modules ALL 17 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 18 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 19 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 20 | ) 21 | 22 | add_custom_target(user_headers ALL 23 | COMMAND ${CMAKE_COMMAND} -E echo "Building Header caches" 24 | COMMAND g++ -fmodules-ts -std=c++20 ${CXX_SOURCE_DIR}/h2.h -c 25 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 26 | ) 27 | 28 | add_dependencies(${TGT} std_modules) 29 | add_dependencies(${TGT} user_headers) 30 | endif() 31 | endfunction() 32 | 33 | set (MODULE_EXT cpp) 34 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 35 | set (MODULE_EXT ixx) 36 | endif() 37 | 38 | add_executable( 39 | ${TARGET} 40 | src/helloworld.${MODULE_EXT} 41 | src/main.cpp 42 | ) 43 | target_include_directories( 44 | ${TARGET} 45 | PRIVATE 46 | src 47 | ) 48 | target_sources( 49 | ${TARGET} 50 | PRIVATE 51 | src/h2.h 52 | ) 53 | 54 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 55 | prepare_for_module(${TARGET}) 56 | endif() 57 | -------------------------------------------------------------------------------- /02/04-GlobalModuleFragment/src/h2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define H2 (H1 + 1) -------------------------------------------------------------------------------- /02/04-GlobalModuleFragment/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #define H1 (1) 4 | #include "h2.h" 5 | 6 | export module helloworld; 7 | 8 | import ; 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | std::cout << "Hello2 " << H1 << std::endl; 13 | std::cout << "Hello2 " << H2 << std::endl; 14 | } -------------------------------------------------------------------------------- /02/04-GlobalModuleFragment/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #define H1 (1) 4 | #include "h2.h" 5 | 6 | export module helloworld; 7 | 8 | import ; 9 | 10 | export void hello() { 11 | std::cout << "Hello world!" << std::endl; 12 | std::cout << "Hello2 " << H1 << std::endl; 13 | std::cout << "Hello2 " << H2 << std::endl; 14 | } -------------------------------------------------------------------------------- /02/04-GlobalModuleFragment/src/main.cpp: -------------------------------------------------------------------------------- 1 | import helloworld; 2 | 3 | int main() { 4 | hello(); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /02/05-PrivateModuleFragment/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 05-PrivateModuleFragment) 4 | project(${TARGET}) 5 | 6 | set(CMAKE_CXX_STANDARD 20) 7 | set(CMAKE_CXX_STANDARD_REQUIRED True) 8 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 9 | 10 | 11 | function (prepare_for_module TGT) 12 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 13 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 14 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 15 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 16 | add_custom_target(std_modules ALL 17 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 18 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 19 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 20 | ) 21 | 22 | add_custom_target(user_headers ALL 23 | COMMAND ${CMAKE_COMMAND} -E echo "Building Header caches" 24 | COMMAND g++ -fmodules-ts -std=c++20 ${CXX_SOURCE_DIR}/h2.h -c 25 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 26 | ) 27 | 28 | add_dependencies(${TGT} std_modules) 29 | add_dependencies(${TGT} user_headers) 30 | endif() 31 | endfunction() 32 | 33 | set (MODULE_EXT cpp) 34 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 35 | set (MODULE_EXT ixx) 36 | endif() 37 | 38 | add_executable( 39 | ${TARGET} 40 | src/helloworld.${MODULE_EXT} 41 | src/main.cpp 42 | ) 43 | target_include_directories( 44 | ${TARGET} 45 | PRIVATE 46 | src 47 | ) 48 | target_sources( 49 | ${TARGET} 50 | PRIVATE 51 | src/h2.h 52 | ) 53 | 54 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 55 | prepare_for_module(${TARGET}) 56 | endif() 57 | -------------------------------------------------------------------------------- /02/05-PrivateModuleFragment/src/h2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define H2 (H1 + 1) -------------------------------------------------------------------------------- /02/05-PrivateModuleFragment/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #define H1 (1) 4 | #include "h2.h" 5 | 6 | export module helloworld; 7 | 8 | import ; 9 | 10 | export void hello(); 11 | 12 | module : private; 13 | 14 | void hiddenHello(); 15 | 16 | void hello() { 17 | std::cout << "Hello world!" << std::endl; 18 | std::cout << "Hello2 " << H1 << std::endl; 19 | std::cout << "Hello2 " << H2 << std::endl; 20 | hiddenHello(); 21 | } 22 | 23 | void hiddenHello() { 24 | std::cout << "Hidden Hello!" << std::endl; 25 | } -------------------------------------------------------------------------------- /02/05-PrivateModuleFragment/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #define H1 (1) 4 | #include "h2.h" 5 | 6 | export module helloworld; 7 | 8 | import ; 9 | 10 | export void hello(); 11 | 12 | module : private; 13 | 14 | void hiddenHello(); 15 | 16 | void hello() { 17 | std::cout << "Hello world!" << std::endl; 18 | std::cout << "Hello2 " << H1 << std::endl; 19 | std::cout << "Hello2 " << H2 << std::endl; 20 | hiddenHello(); 21 | } 22 | 23 | void hiddenHello() { 24 | std::cout << "Hidden Hello!" << std::endl; 25 | } -------------------------------------------------------------------------------- /02/05-PrivateModuleFragment/src/main.cpp: -------------------------------------------------------------------------------- 1 | import helloworld; 2 | 3 | int main() { 4 | hello(); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /02/06-ModulePartition/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 06-ModulePartition) 4 | project(${TARGET}) 5 | 6 | set(CMAKE_CXX_STANDARD 20) 7 | set(CMAKE_CXX_STANDARD_REQUIRED True) 8 | 9 | function (prepare_for_module TGT) 10 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 11 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 12 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 13 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 14 | add_custom_target(std_modules ALL 15 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 16 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint 17 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 18 | ) 19 | 20 | add_dependencies(${TGT} std_modules) 21 | endif() 22 | endfunction() 23 | 24 | set (MODULE_EXT cpp) 25 | 26 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 27 | set (MODULE_EXT ixx) 28 | endif() 29 | 30 | add_executable( 31 | ${TARGET} 32 | src/helloworldA.${MODULE_EXT} 33 | src/helloworldB.${MODULE_EXT} 34 | src/helloworld.${MODULE_EXT} 35 | src/main.cpp 36 | ) 37 | 38 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 39 | prepare_for_module(${TARGET}) 40 | endif() 41 | -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworld.cpp: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | 5 | export import :A; 6 | import :B; 7 | 8 | export void hello() { 9 | std::cout << "Hello world!" << std::endl; 10 | helloworldA(); 11 | helloworldB(); 12 | } -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworld.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld; 2 | 3 | import ; 4 | 5 | export import :A; 6 | import :B; 7 | 8 | export void hello() { 9 | std::cout << "Hello world!" << std::endl; 10 | helloworldA(); 11 | helloworldB(); 12 | } -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworldA.cpp: -------------------------------------------------------------------------------- 1 | export module helloworld:A; 2 | 3 | import ; 4 | 5 | export void helloworldA(); 6 | 7 | void helloworldA() { 8 | std::cout << "HelloWorldA" << std::endl; 9 | } 10 | -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworldA.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld:A; 2 | 3 | export void helloworldA(); 4 | 5 | import ; 6 | 7 | void helloworldA() { 8 | std::cout << "HelloWorldA" << std::endl; 9 | } -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworldB.cpp: -------------------------------------------------------------------------------- 1 | module helloworld:B; 2 | 3 | import ; 4 | 5 | void helloworldB() { 6 | std::cout << "HelloWorldB" << std::endl; 7 | } 8 | -------------------------------------------------------------------------------- /02/06-ModulePartition/src/helloworldB.ixx: -------------------------------------------------------------------------------- 1 | export module helloworld:B; 2 | 3 | import ; 4 | 5 | void helloworldB() { 6 | std::cout << "HelloWorldB" << std::endl; 7 | } -------------------------------------------------------------------------------- /02/06-ModulePartition/src/main.cpp: -------------------------------------------------------------------------------- 1 | import helloworld; 2 | 3 | int main() { 4 | hello(); 5 | 6 | return 0; 7 | } -------------------------------------------------------------------------------- /03/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET ImageProcessorUniversal) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | 10 | function (prepare_for_module TGT) 11 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 12 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 13 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 14 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 15 | add_custom_target(std_modules ALL 16 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 17 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream string vector map functional cstdint memory 18 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 19 | ) 20 | 21 | add_dependencies(${TGT} std_modules) 22 | endif() 23 | endfunction() 24 | 25 | set (MODULE_EXT cpp) 26 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 27 | set (MODULE_EXT ixx) 28 | endif() 29 | 30 | add_executable( 31 | ${TARGET} 32 | src/command/argument.${MODULE_EXT} 33 | src/command/parser.${MODULE_EXT} 34 | src/command/command.${MODULE_EXT} 35 | src/network/request.${MODULE_EXT} 36 | src/network/response.${MODULE_EXT} 37 | src/network/connection.${MODULE_EXT} 38 | src/network/server.${MODULE_EXT} 39 | src/network/network.${MODULE_EXT} 40 | src/cache/loader.${MODULE_EXT} 41 | src/cache/cache.${MODULE_EXT} 42 | src/image/processor.${MODULE_EXT} 43 | src/image/image.${MODULE_EXT} 44 | src/app/app.${MODULE_EXT} 45 | src/main.cpp 46 | ) 47 | 48 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 49 | prepare_for_module(${TARGET}) 50 | endif() 51 | -------------------------------------------------------------------------------- /03/src/app/app.cpp: -------------------------------------------------------------------------------- 1 | export module ips.app; 2 | 3 | import ; 4 | import ; 5 | 6 | import ips.network; 7 | import ips.image; 8 | import ips.cache; 9 | 10 | namespace ips::app { 11 | export void processRequest( 12 | ips::cache::CacheLoader* cacheLoader, 13 | ips::network::RequestPtr request, 14 | ips::network::ResponsePtr response 15 | ) { 16 | const std::string& path = request->getPath(); 17 | const std::map& query = request->getQuery(); 18 | std::string data = request->getBody(); 19 | ips::image::Processor imageProcessor; 20 | std::string cacheKey = path; 21 | 22 | auto widthIterator = query.find("width"); 23 | if (widthIterator != query.cend()) { 24 | imageProcessor.setWidth(std::stoi(widthIterator->second)); 25 | cacheKey += "&width=" + widthIterator->second; 26 | } 27 | 28 | auto heighIterator = query.find("height"); 29 | if (heighIterator != query.cend()) { 30 | imageProcessor.setHeight(std::stoi(heighIterator->second)); 31 | cacheKey += "&height=" + heighIterator->second; 32 | } 33 | 34 | auto qualityIterator = query.find("quality"); 35 | if (qualityIterator != query.cend()) { 36 | imageProcessor.setQuality(std::stoi(qualityIterator->second)); 37 | cacheKey += "&quality=" + qualityIterator->second; 38 | } 39 | 40 | auto modeIterator = query.find("mode"); 41 | if (modeIterator != query.cend()) { 42 | imageProcessor.setMode(modeIterator->second); 43 | cacheKey += "&mode=" + modeIterator->second; 44 | } 45 | 46 | std::string processedImageData; 47 | bool hasCache = cacheLoader->loadCacheFile(cacheKey, &processedImageData); 48 | if (hasCache) { 49 | response->send(processedImageData); 50 | 51 | return; 52 | } 53 | 54 | processedImageData = imageProcessor.processImage(data); 55 | response->send(processedImageData); 56 | } 57 | } -------------------------------------------------------------------------------- /03/src/app/app.ixx: -------------------------------------------------------------------------------- 1 | export module ips.app; 2 | 3 | import ; 4 | import ; 5 | 6 | import ips.network; 7 | import ips.image; 8 | import ips.cache; 9 | 10 | namespace ips::app { 11 | export void processRequest( 12 | ips::cache::CacheLoader* cacheLoader, 13 | ips::network::RequestPtr request, 14 | ips::network::ResponsePtr response 15 | ) { 16 | const std::string& path = request->getPath(); 17 | const std::map& query = request->getQuery(); 18 | std::string data = request->getBody(); 19 | ips::image::Processor imageProcessor; 20 | std::string cacheKey = path; 21 | 22 | auto widthIterator = query.find("width"); 23 | if (widthIterator != query.cend()) { 24 | imageProcessor.setWidth(std::stoi(widthIterator->second)); 25 | cacheKey += "&width=" + widthIterator->second; 26 | } 27 | 28 | auto heighIterator = query.find("height"); 29 | if (heighIterator != query.cend()) { 30 | imageProcessor.setHeight(std::stoi(heighIterator->second)); 31 | cacheKey += "&height=" + heighIterator->second; 32 | } 33 | 34 | auto qualityIterator = query.find("quality"); 35 | if (qualityIterator != query.cend()) { 36 | imageProcessor.setQuality(std::stoi(qualityIterator->second)); 37 | cacheKey += "&quality=" + qualityIterator->second; 38 | } 39 | 40 | auto modeIterator = query.find("mode"); 41 | if (modeIterator != query.cend()) { 42 | imageProcessor.setMode(modeIterator->second); 43 | cacheKey += "&mode=" + modeIterator->second; 44 | } 45 | 46 | std::string processedImageData; 47 | bool hasCache = cacheLoader->loadCacheFile(cacheKey, &processedImageData); 48 | if (hasCache) { 49 | response->send(processedImageData); 50 | 51 | return; 52 | } 53 | 54 | processedImageData = imageProcessor.processImage(data); 55 | response->send(processedImageData); 56 | } 57 | } -------------------------------------------------------------------------------- /03/src/cache/cache.cpp: -------------------------------------------------------------------------------- 1 | export module ips.cache; 2 | 3 | export import :loader; -------------------------------------------------------------------------------- /03/src/cache/cache.ixx: -------------------------------------------------------------------------------- 1 | export module ips.cache; 2 | 3 | export import :loader; -------------------------------------------------------------------------------- /03/src/cache/loader.cpp: -------------------------------------------------------------------------------- 1 | export module ips.cache:loader; 2 | 3 | import ; 4 | 5 | namespace ips::cache { 6 | export class CacheLoader { 7 | public: 8 | CacheLoader(const std::string& basePath) : 9 | _basePath(basePath) {} 10 | 11 | bool loadCacheFile(const std::string& key, std::string* cacheFileData) { 12 | return false; 13 | } 14 | 15 | private: 16 | std::string _basePath; 17 | }; 18 | } -------------------------------------------------------------------------------- /03/src/cache/loader.ixx: -------------------------------------------------------------------------------- 1 | export module ips.cache:loader; 2 | 3 | import ; 4 | 5 | namespace ips::cache { 6 | export class CacheLoader { 7 | public: 8 | CacheLoader(const std::string& basePath) : 9 | _basePath(basePath) {} 10 | 11 | bool loadCacheFile(const std::string& key, std::string* cacheFileData) { 12 | return false; 13 | } 14 | 15 | private: 16 | std::string _basePath; 17 | }; 18 | } -------------------------------------------------------------------------------- /03/src/command/argument.cpp: -------------------------------------------------------------------------------- 1 | export module ips.command:argument; 2 | 3 | import ; 4 | 5 | namespace ips::command { 6 | export class Argument { 7 | public: 8 | Argument( 9 | const std::string& flag, 10 | const std::string& name, 11 | const std::string& helpMessage = "", 12 | bool required = false 13 | ) : 14 | _flag(flag), 15 | _name(name), 16 | _helpMessage(helpMessage), 17 | _required(required) 18 | {} 19 | 20 | const std::string& getFlag() const { 21 | return _flag; 22 | } 23 | 24 | void setFlag(const std::string& flag) { 25 | _flag = flag; 26 | } 27 | 28 | const std::string& getHelpMessage() const { 29 | return _helpMessage; 30 | } 31 | 32 | void setHelpMessage(const std::string& helpMessage) { 33 | _helpMessage = helpMessage; 34 | } 35 | 36 | bool isRequired() const { 37 | return _required; 38 | } 39 | 40 | void setRequired(bool required) { 41 | _required = required; 42 | } 43 | 44 | private: 45 | std::string _flag; 46 | std::string _name; 47 | std::string _helpMessage; 48 | bool _required; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /03/src/command/argument.ixx: -------------------------------------------------------------------------------- 1 | export module ips.command:argument; 2 | 3 | import ; 4 | 5 | namespace ips::command { 6 | export class Argument { 7 | public: 8 | Argument( 9 | const std::string& flag, 10 | const std::string& name, 11 | const std::string& helpMessage = "", 12 | bool required = false 13 | ) : 14 | _flag(flag), 15 | _name(name), 16 | _helpMessage(helpMessage), 17 | _required(required) 18 | {} 19 | 20 | const std::string& getFlag() const { 21 | return _flag; 22 | } 23 | 24 | void setFlag(const std::string& flag) { 25 | _flag = flag; 26 | } 27 | 28 | const std::string& getHelpMessage() const { 29 | return _helpMessage; 30 | } 31 | 32 | void setHelpMessage(const std::string& helpMessage) { 33 | _helpMessage = helpMessage; 34 | } 35 | 36 | bool isRequired() const { 37 | return _required; 38 | } 39 | 40 | void setRequired(bool required) { 41 | _required = required; 42 | } 43 | 44 | private: 45 | std::string _flag; 46 | std::string _name; 47 | std::string _helpMessage; 48 | bool _required; 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /03/src/command/command.cpp: -------------------------------------------------------------------------------- 1 | export module ips.command; 2 | 3 | export import :parser; 4 | export import :argument; -------------------------------------------------------------------------------- /03/src/command/command.ixx: -------------------------------------------------------------------------------- 1 | export module ips.command; 2 | 3 | export import :parser; 4 | export import :argument; -------------------------------------------------------------------------------- /03/src/command/parser.cpp: -------------------------------------------------------------------------------- 1 | export module ips.command:parser; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | 8 | import :argument; 9 | 10 | namespace ips::command { 11 | export class Parser { 12 | public: 13 | Parser& addArgument(const Argument& argument) { 14 | _arguments.push_back(argument); 15 | 16 | return *this; 17 | } 18 | 19 | std::map parseArgs() { 20 | return _parsedArgs; 21 | } 22 | 23 | std::string getNamedArgument(const std::string& name) { 24 | std::string value = _parsedArgs[name]; 25 | 26 | return value; 27 | } 28 | 29 | template 30 | T getNamedArgument(const std::string& name, std::function converter) { 31 | std::string value = _parsedArgs[name]; 32 | 33 | return converter(value); 34 | } 35 | 36 | private: 37 | std::vector _arguments; 38 | std::map _parsedArgs; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /03/src/command/parser.ixx: -------------------------------------------------------------------------------- 1 | export module ips.command:parser; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | 8 | import :argument; 9 | 10 | namespace ips::command { 11 | export class Parser { 12 | public: 13 | Parser& addArgument(const Argument& argument) { 14 | _arguments.push_back(argument); 15 | 16 | return *this; 17 | } 18 | 19 | std::map parseArgs() { 20 | return _parsedArgs; 21 | } 22 | 23 | std::string getNamedArgument(const std::string& name) { 24 | std::string value = _parsedArgs[name]; 25 | 26 | return value; 27 | } 28 | 29 | template 30 | T getNamedArgument(const std::string& name, std::function converter) { 31 | std::string value = _parsedArgs[name]; 32 | 33 | return converter(value); 34 | } 35 | 36 | private: 37 | std::vector _arguments; 38 | std::map _parsedArgs; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /03/src/image/image.cpp: -------------------------------------------------------------------------------- 1 | export module ips.image; 2 | 3 | export import :processor; -------------------------------------------------------------------------------- /03/src/image/image.ixx: -------------------------------------------------------------------------------- 1 | export module ips.image; 2 | 3 | export import :processor; -------------------------------------------------------------------------------- /03/src/image/processor.cpp: -------------------------------------------------------------------------------- 1 | export module ips.image:processor; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::image{ 7 | export class Processor { 8 | public: 9 | void setWidth(int32_t width) { 10 | _width = width; 11 | } 12 | 13 | int32_t getWidth() const { 14 | return _width; 15 | } 16 | 17 | void setHeight(int32_t height) { 18 | _height = height; 19 | } 20 | 21 | int32_t getHeight() const { 22 | return _height; 23 | } 24 | 25 | void setQuality(int32_t quality) { 26 | _quality = quality; 27 | } 28 | 29 | int32_t getQuality() const { 30 | return _quality; 31 | } 32 | 33 | void setMode(const std::string& mode) { 34 | _mode = mode; 35 | } 36 | 37 | const std::string& getMode() const { 38 | return _mode; 39 | } 40 | 41 | std::string&& processImage(const std::string& data) { 42 | return ""; 43 | } 44 | 45 | private: 46 | int32_t _width; 47 | int32_t _height; 48 | int32_t _quality; 49 | std::string _mode; 50 | }; 51 | } -------------------------------------------------------------------------------- /03/src/image/processor.ixx: -------------------------------------------------------------------------------- 1 | export module ips.image:processor; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::image{ 7 | export class Processor { 8 | public: 9 | void setWidth(int32_t width) { 10 | _width = width; 11 | } 12 | 13 | int32_t getWidth() const { 14 | return _width; 15 | } 16 | 17 | void setHeight(int32_t height) { 18 | _height = height; 19 | } 20 | 21 | int32_t getHeight() const { 22 | return _height; 23 | } 24 | 25 | void setQuality(int32_t quality) { 26 | _quality = quality; 27 | } 28 | 29 | int32_t getQuality() const { 30 | return _quality; 31 | } 32 | 33 | void setMode(const std::string& mode) { 34 | _mode = mode; 35 | } 36 | 37 | const std::string& getMode() const { 38 | return _mode; 39 | } 40 | 41 | std::string&& processImage(const std::string& data) { 42 | return ""; 43 | } 44 | 45 | private: 46 | int32_t _width; 47 | int32_t _height; 48 | int32_t _quality; 49 | std::string _mode; 50 | }; 51 | } -------------------------------------------------------------------------------- /03/src/main.cpp: -------------------------------------------------------------------------------- 1 | import ; 2 | import ; 3 | import ; 4 | 5 | import ips.command; 6 | import ips.network; 7 | import ips.image; 8 | import ips.app; 9 | import ips.cache; 10 | 11 | int main() { 12 | std::cout << "Image Processor" << std::endl; 13 | 14 | ips::command::Parser parser; 15 | parser.addArgument(ips::command::Argument("--host", "host")); 16 | parser.addArgument(ips::command::Argument("--port", "port")); 17 | parser.addArgument(ips::command::Argument("--cache", "cachePath")); 18 | parser.parseArgs(); 19 | 20 | std::string cachePath = parser.getNamedArgument("cachePath"); 21 | ips::cache::CacheLoader cacheLoader(cachePath); 22 | 23 | std::string host = parser.getNamedArgument("host"); 24 | int port = parser.getNamedArgument("port", [](const std::string& value)-> int32_t { 25 | return std::stoi(value); 26 | }); 27 | ips::network::Server server(host, port); 28 | 29 | server.onConnection([&cacheLoader](ips::network::ConnectionPtr connection) -> void { 30 | connection->onRequest(std::bind( 31 | ips::app::processRequest, 32 | &cacheLoader, 33 | std::placeholders::_1, 34 | std::placeholders::_2 35 | )); 36 | }); 37 | 38 | server.startListen(); 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /03/src/network/connection.cpp: -------------------------------------------------------------------------------- 1 | export module ips.network:connection; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | import :request; 8 | import :response; 9 | 10 | namespace ips::network { 11 | export using RequestPtr = std::shared_ptr; 12 | export using ResponsePtr = std::shared_ptr; 13 | 14 | export using OnRequestHandler = std::function; 15 | 16 | export class Connection { 17 | public: 18 | Connection() {} 19 | 20 | void onRequest(OnRequestHandler requestHandler) { 21 | _requestHandlers.push_back(requestHandler); 22 | } 23 | 24 | private: 25 | std::vector _requestHandlers; 26 | }; 27 | } -------------------------------------------------------------------------------- /03/src/network/connection.ixx: -------------------------------------------------------------------------------- 1 | export module ips.network:connection; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | import :request; 8 | import :response; 9 | 10 | namespace ips::network { 11 | export using RequestPtr = std::shared_ptr; 12 | export using ResponsePtr = std::shared_ptr; 13 | 14 | export using OnRequestHandler = std::function; 15 | 16 | export class Connection { 17 | public: 18 | Connection() {} 19 | 20 | void onRequest(OnRequestHandler requestHandler) { 21 | _requestHandlers.push_back(requestHandler); 22 | } 23 | 24 | private: 25 | std::vector _requestHandlers; 26 | }; 27 | } -------------------------------------------------------------------------------- /03/src/network/network.cpp: -------------------------------------------------------------------------------- 1 | export module ips.network; 2 | 3 | export import :server; 4 | export import :request; 5 | export import :response; 6 | export import :connection; 7 | -------------------------------------------------------------------------------- /03/src/network/network.ixx: -------------------------------------------------------------------------------- 1 | export module ips.network; 2 | 3 | export import :server; 4 | export import :request; 5 | export import :response; 6 | export import :connection; 7 | -------------------------------------------------------------------------------- /03/src/network/request.cpp: -------------------------------------------------------------------------------- 1 | export module ips.network:request; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::network { 7 | export class Request { 8 | public: 9 | Request() {} 10 | 11 | void setPath(const std::string& path) { 12 | _path = path; 13 | } 14 | 15 | const std::string& getPath() { 16 | return _path; 17 | } 18 | 19 | void setQuery(const std::map& query) { 20 | _query = query; 21 | } 22 | 23 | const std::map& getQuery() { 24 | return _query; 25 | } 26 | 27 | std::string&& getBody() { 28 | return ""; 29 | } 30 | 31 | private: 32 | std::string _path; 33 | std::map _query; 34 | }; 35 | } -------------------------------------------------------------------------------- /03/src/network/request.ixx: -------------------------------------------------------------------------------- 1 | export module ips.network:request; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::network { 7 | export class Request { 8 | public: 9 | Request() {} 10 | 11 | void setPath(const std::string& path) { 12 | _path = path; 13 | } 14 | 15 | const std::string& getPath() { 16 | return _path; 17 | } 18 | 19 | void setQuery(const std::map& query) { 20 | _query = query; 21 | } 22 | 23 | const std::map& getQuery() { 24 | return _query; 25 | } 26 | 27 | std::string&& getBody() { 28 | return ""; 29 | } 30 | 31 | private: 32 | std::string _path; 33 | std::map _query; 34 | }; 35 | } -------------------------------------------------------------------------------- /03/src/network/response.cpp: -------------------------------------------------------------------------------- 1 | export module ips.network:response; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::network{ 7 | export class Response { 8 | public: 9 | Response() {} 10 | 11 | void send(const std::string& data) { 12 | std::cout << "Sent data" << data.size() << std::endl; 13 | } 14 | }; 15 | } -------------------------------------------------------------------------------- /03/src/network/response.ixx: -------------------------------------------------------------------------------- 1 | export module ips.network:response; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace ips::network{ 7 | export class Response { 8 | public: 9 | Response() {} 10 | 11 | void send(const std::string& data) { 12 | std::cout << "Sent data" << data.size() << std::endl; 13 | } 14 | }; 15 | } -------------------------------------------------------------------------------- /03/src/network/server.cpp: -------------------------------------------------------------------------------- 1 | export module ips.network:server; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | import ; 9 | 10 | import :connection; 11 | 12 | namespace ips::network { 13 | export using ConnectionPtr = std::shared_ptr; 14 | export using OnConnectionHandler = std::function; 15 | 16 | export class Server { 17 | public: 18 | Server(const std::string& host, int32_t port) : 19 | _host(host), _port(port) {} 20 | 21 | void setHost(const std::string& host) { 22 | _host = host; 23 | } 24 | 25 | const std::string& getHost() const { 26 | return _host; 27 | } 28 | 29 | void setPort(int32_t port) { 30 | _port = port; 31 | } 32 | 33 | int32_t getPort() const { 34 | return _port; 35 | } 36 | 37 | void startListen() { 38 | std::cout << "Start listened at " << _host << ":" << _port << std::endl; 39 | } 40 | 41 | void onConnection(OnConnectionHandler handler) { 42 | _handlers.push_back(handler); 43 | } 44 | 45 | private: 46 | std::string _host; 47 | int32_t _port; 48 | std::vector _handlers; 49 | }; 50 | } -------------------------------------------------------------------------------- /03/src/network/server.ixx: -------------------------------------------------------------------------------- 1 | export module ips.network:server; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | import ; 9 | 10 | import :connection; 11 | 12 | namespace ips::network { 13 | export using ConnectionPtr = std::shared_ptr; 14 | export using OnConnectionHandler = std::function; 15 | 16 | export class Server { 17 | public: 18 | Server(const std::string& host, int32_t port) : 19 | _host(host), _port(port) {} 20 | 21 | void setHost(const std::string& host) { 22 | _host = host; 23 | } 24 | 25 | const std::string& getHost() const { 26 | return _host; 27 | } 28 | 29 | void setPort(int32_t port) { 30 | _port = port; 31 | } 32 | 33 | int32_t getPort() const { 34 | return _port; 35 | } 36 | 37 | void startListen() { 38 | std::cout << "Start listened at " << _host << ":" << _port << std::endl; 39 | } 40 | 41 | void onConnection(OnConnectionHandler handler) { 42 | _handlers.push_back(handler); 43 | } 44 | 45 | private: 46 | std::string _host; 47 | int32_t _port; 48 | std::vector _handlers; 49 | }; 50 | } -------------------------------------------------------------------------------- /04/01-BasicTemplate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 01-BasicTemplate) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | add_executable( 12 | ${TARGET} 13 | src/main.cpp 14 | src/c11.cpp 15 | ) 16 | target_include_directories( 17 | ${TARGET} 18 | PRIVATE 19 | src 20 | ) 21 | target_sources( 22 | ${TARGET} 23 | PRIVATE 24 | src/c11.h 25 | ) 26 | -------------------------------------------------------------------------------- /04/01-BasicTemplate/src/c11.cpp: -------------------------------------------------------------------------------- 1 | #include "c11.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | template <> 9 | void fillContainer, float>(std::vector& collection, float value, size_t size) { 10 | std::cout << "Explicit (full) template specialization" << std::endl; 11 | for (size_t i = 0; i != size; ++i) { 12 | collection.push_back(static_cast(value)); 13 | } 14 | } 15 | 16 | template 17 | void fillContainer, int32_t>(std::vector& collection, int32_t value, size_t size); 18 | 19 | void c11() { 20 | std::vector vec; 21 | fillContainer<10>(vec, 0); 22 | fillContainer(vec, 0, 10); 23 | 24 | std::list lst; 25 | fillContainer<10, std::list>(lst, 1); 26 | 27 | std::deque deq; 28 | fillContainer<10, std::deque, int32_t>(deq, 2); 29 | } 30 | -------------------------------------------------------------------------------- /04/01-BasicTemplate/src/c11.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template 6 | void fillContainer(T& collection, U value) { 7 | for (size_t i = 0; i != Size; ++i) { 8 | collection.push_back(value); 9 | } 10 | } 11 | 12 | template 13 | void fillContainer(T& collection, U value, size_t size) { 14 | std::cout << "Universal" << std::endl; 15 | 16 | for (size_t i = 0; i != size; ++i) { 17 | collection.push_back(value); 18 | } 19 | } 20 | 21 | void c11(); 22 | -------------------------------------------------------------------------------- /04/01-BasicTemplate/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "c11.h" 2 | 3 | int main() { 4 | c11(); 5 | } 6 | -------------------------------------------------------------------------------- /04/02-Specializations/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 02-Specializations) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | add_executable( 12 | ${TARGET} 13 | src/main.cpp 14 | ) 15 | target_include_directories( 16 | ${TARGET} 17 | PRIVATE 18 | src 19 | ) 20 | target_sources( 21 | ${TARGET} 22 | PRIVATE 23 | src/c13.h 24 | ) 25 | -------------------------------------------------------------------------------- /04/02-Specializations/src/c13.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | template 7 | void fillContainer(T& collection, U value) { 8 | std::cout << "Universal" << std::endl; 9 | 10 | for (size_t i = 0; i != Size; ++i) { 11 | collection.push_back(value); 12 | } 13 | } 14 | 15 | template <> 16 | void fillContainer<10, std::vector, double>( 17 | std::vector& collection, double value 18 | ) { 19 | std::cout << "Explicit (full) template specialization" << std::endl; 20 | 21 | for (size_t i = 0; i != 10; ++i) { 22 | collection.push_back(value + 2.0); 23 | } 24 | } 25 | 26 | void c13() { 27 | std::vector intVec; 28 | fillContainer<5>(intVec, 10); 29 | 30 | std::vector doubleVec; 31 | fillContainer<10>(doubleVec, 10.0); 32 | } 33 | -------------------------------------------------------------------------------- /04/02-Specializations/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "c13.h" 2 | 3 | int main() { 4 | c13(); 5 | } 6 | -------------------------------------------------------------------------------- /04/03-ParamterPack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 03-ParameterPack) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | add_executable( 12 | ${TARGET} 13 | src/main.cpp 14 | ) 15 | -------------------------------------------------------------------------------- /04/03-ParamterPack/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | double sum() { 5 | return 0.0; 6 | } 7 | 8 | template 9 | double sum(T value, Targs... Fargs) { 10 | return static_cast(value) + sum(Fargs...); 11 | } 12 | 13 | template 14 | void countArgs(Targs... args) { 15 | std::cout << "count: " << sizeof...(args) << std::endl; 16 | } 17 | 18 | int main() { 19 | double a1 = sum(); 20 | double a2 = sum(1); 21 | double a3 = sum(2, 3); 22 | double a4 = sum(4, 5, 6); 23 | double a5 = sum(7, 8.0f, 9, 10.0); 24 | 25 | std::cout << "a1: " << a1 << std::endl; 26 | std::cout << "a2: " << a2 << std::endl; 27 | std::cout << "a3: " << a3 << std::endl; 28 | std::cout << "a4: " << a4 << std::endl; 29 | std::cout << "a5: " << a5 << std::endl; 30 | 31 | countArgs(); 32 | countArgs(1); 33 | countArgs(1, 1.0f); 34 | countArgs(1, 1.0f, 3.0); 35 | countArgs(1, 1.0f, 3.0, "hello"); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /04/04-TypeTraits/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 04-TypeTraits) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | add_executable( 12 | ${TARGET} 13 | src/main.cpp 14 | ) 15 | -------------------------------------------------------------------------------- /04/04-TypeTraits/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | template , 11 | T 12 | >::value, 13 | bool 14 | > = true> 15 | void printCollection(const T& a) { 16 | std::cout << "List version" << std::endl; 17 | 18 | for (auto element : a) { 19 | std::cout << element << " "; 20 | } 21 | 22 | std::cout << std::endl; 23 | } 24 | 25 | template , 29 | T 30 | >::value, 31 | bool 32 | > = true> 33 | void printCollection(const T& a) { 34 | std::cout << "Vector version" << std::endl; 35 | 36 | for (auto element : a) { 37 | std::cout << element << " "; 38 | } 39 | 40 | std::cout << std::endl; 41 | } 42 | 43 | void c14() { 44 | std::vector arr1{ 45 | 1, 2, 3, 4, 5 46 | }; 47 | printCollection(arr1); 48 | 49 | std::list arr2{ 50 | 1, 2, 3, 4, 5 51 | }; 52 | printCollection(arr2); 53 | } 54 | 55 | int main() { 56 | c14(); 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /04/05-ErrorMessage/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 05-ErrorMessage) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | add_executable( 12 | ${TARGET} 13 | src/main.cpp 14 | ) 15 | -------------------------------------------------------------------------------- /04/05-ErrorMessage/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class TestClass { 5 | public: 6 | TestClass(const TestClass&) = delete; 7 | 8 | int32_t getValue2() const { 9 | return 0; 10 | } 11 | }; 12 | 13 | void c10() { 14 | std::vector v(10); 15 | v[0] = v[1]; 16 | } 17 | 18 | int main() { 19 | c10(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /05/01-BasicConcepts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 01-BasicConcepts) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/01-BasicConcepts/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class BaseClass { 5 | public: 6 | int getValue() const { 7 | return 1; 8 | } 9 | }; 10 | 11 | class DerivedClass: public BaseClass { 12 | public: 13 | int getValue() const { 14 | return 2; 15 | } 16 | }; 17 | 18 | class NonDerivedClass { 19 | public: 20 | int getValue() const { 21 | return 3; 22 | } 23 | }; 24 | 25 | template 26 | concept DerivedOfBaseClass = std::is_base_of_v; 27 | 28 | template 29 | void doGetValue(const T& a) { 30 | std::cout << "Get value:" << a.getValue() << std::endl; 31 | } 32 | 33 | int c2() { 34 | DerivedClass d; 35 | doGetValue(d); 36 | 37 | BaseClass b; 38 | doGetValue(b); 39 | 40 | // 解除注释会引发错误 41 | // NonDerivedClass n; 42 | // doGetValue(n); 43 | 44 | return 0; 45 | } 46 | 47 | int main() { 48 | c2(); 49 | 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /05/02-Conjunctions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 02-Conjunctions) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/02-Conjunctions/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | constexpr bool get_value() { return T::value; } 6 | 7 | template 8 | requires (sizeof(T) > 1 && get_value()) 9 | void f(T) { 10 | std::cout << "template version" << std::endl; 11 | } 12 | 13 | void f(int32_t) { 14 | std::cout << "int version" << std::endl; 15 | } 16 | 17 | void c15() { 18 | f('A'); 19 | } 20 | 21 | int main() { 22 | c15(); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /05/03-Disjunctions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 03-Disjunctions) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/03-Disjunctions/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | concept Integral = std::is_integral_v; 6 | 7 | template 8 | concept FloatingPoint = std::is_floating_point_v; 9 | 10 | template 11 | concept Number = Integral || FloatingPoint; 12 | 13 | template 14 | void f3(T a) { 15 | std::cout << a << std::endl; 16 | } 17 | 18 | void c3() { 19 | f3(5); 20 | f3(20.0f); 21 | f3(30.0); 22 | // 解除注释会引发错误 23 | // f3("aaa"); 24 | } 25 | 26 | int main() { 27 | c3(); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /05/04-AutomicConstraints/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 04-AutomicConstraints) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/04-AutomicConstraints/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | template 6 | struct S { 7 | constexpr operator bool() const { return true; } 8 | }; 9 | 10 | // 约束检查编译失败 11 | // template 12 | // requires (S{}) 13 | // void f1(T) { 14 | // std::cout << "Template" << std::endl; 15 | // } 16 | 17 | // 约束检查编译失败 18 | // template 19 | // requires (1) 20 | // void f2(T) { 21 | // std::cout << "Template" << std::endl; 22 | // } 23 | 24 | template 25 | requires (static_cast(S{})) 26 | void f3(T) { 27 | std::cout << "Template" << std::endl; 28 | } 29 | 30 | template 31 | concept Floating = std::is_floating_point_v; 32 | 33 | template 34 | concept BadNumber = std::is_floating_point_v && std::is_floating_point_v; 35 | 36 | template 37 | concept Number = Floating && std::is_floating_point_v; 38 | 39 | template // #1 40 | void func(T) {} 41 | 42 | // 解除注释会引发错误 43 | // template // #2 44 | // void func(T) {} 45 | 46 | template // #3 47 | void func(T) {} 48 | 49 | int main() { 50 | func(1.0f); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /05/05-RequiresExpressions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 05-RequiresExpressions) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/05-RequiresExpressions/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::same_as; 7 | using std::convertible_to; 8 | 9 | template 10 | concept Histogram = requires(T h1, T h2) { 11 | h1.getMoments(); // 要求有getMoments接口 12 | T::count; // 要求有静态变量count 13 | h1.moments; // 要求有成员变量moments 14 | h1 + h2; // 要求对象能够进行+操作 15 | 16 | typename T::type; // 要求存在类型成员type 17 | typename std::vector; // 要求能够模板实例化并与std::vector组合使用 18 | 19 | { h1.getSubHistogram() } -> same_as; // 要求接口返回类型与T一致 20 | { h1.getUnit() } -> convertible_to; // 要求接口返回类型能转换成float,本质上接口返回类型可能是double 21 | { h1 = std::move(h2) } noexcept; // 要求表达式不能抛出异常 22 | 23 | requires sizeof(T) > 4; 24 | }; 25 | 26 | int main() { 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /05/06-RequiresClauses/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 06-RequiresClauses) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /05/06-RequiresClauses/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | requires requires (T1 x, T2 y) { x + y; } 6 | std::common_type func( 7 | T1 arg1, T2 arg2 8 | ) { 9 | return arg1 + arg2; 10 | } 11 | 12 | int main() { 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /06/NumCpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET NumCpp) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 12 | add_custom_target(std_modules ALL 13 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 14 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint concepts type_traits vector initializer_list tuple cstring memory algorithm stdexcept array 15 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 16 | ) 17 | 18 | add_dependencies(${TGT} std_modules) 19 | endif() 20 | 21 | function (prepare_for_module TGT) 22 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 23 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 24 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 25 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 26 | add_dependencies(${TGT} std_modules) 27 | endif() 28 | endfunction() 29 | 30 | set (MODULE_EXT cpp) 31 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 32 | set (MODULE_EXT ixx) 33 | add_compile_options(/utf-8) 34 | endif() 35 | 36 | add_executable( 37 | ${TARGET} 38 | src/numcpp/concepts.${MODULE_EXT} 39 | src/numcpp/types.${MODULE_EXT} 40 | src/numcpp/utils.${MODULE_EXT} 41 | src/numcpp/array_view.${MODULE_EXT} 42 | src/numcpp/array.${MODULE_EXT} 43 | src/numcpp/creation.${MODULE_EXT} 44 | src/numcpp/algorithm/basic.${MODULE_EXT} 45 | src/numcpp/algorithm/universal.${MODULE_EXT} 46 | src/numcpp/algorithm/aggregate.${MODULE_EXT} 47 | src/numcpp/algorithm/algorithm.${MODULE_EXT} 48 | src/numcpp/numcpp.${MODULE_EXT} 49 | src/main.cpp 50 | ) 51 | 52 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 53 | prepare_for_module(${TARGET}) 54 | endif() 55 | -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/algorithm/algorithm.cpp: -------------------------------------------------------------------------------- 1 | export module numcpp:algorithm; 2 | 3 | export import :algorithm.basic; 4 | export import :algorithm.aggregate; 5 | export import :algorithm.universal; -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/algorithm/algorithm.ixx: -------------------------------------------------------------------------------- 1 | export module numcpp:algorithm; 2 | 3 | export import :algorithm.basic; 4 | export import :algorithm.aggregate; 5 | export import :algorithm.universal; -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/concepts.cpp: -------------------------------------------------------------------------------- 1 | export module numcpp:concepts; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace numcpp { 7 | template 8 | concept Integral = std::is_integral_v; 9 | 10 | template 11 | concept FloatingPoint = std::is_floating_point_v; 12 | 13 | template 14 | concept Number = Integral || FloatingPoint; 15 | 16 | template 17 | using IteratorMemberFunction = T::iterator(T::*)(); 18 | 19 | template 20 | concept HasBegin = std::is_member_function_pointer_v< 21 | decltype( 22 | IteratorMemberFunction(&T::begin) 23 | ) 24 | >; 25 | 26 | template 27 | concept HasEnd = std::is_member_function_pointer_v< 28 | decltype( 29 | IteratorMemberFunction(&T::end) 30 | ) 31 | >; 32 | 33 | template 34 | concept IsIterable = HasBegin && HasEnd; 35 | 36 | template 37 | concept IsNumberIterable = IsIterable && Number; 38 | 39 | //template 40 | //concept AnyConvertible = std::is_convertible_v || std::is_convertible_v; 41 | 42 | template 43 | concept AnyConvertible = requires { 44 | typename std::common_type_t; 45 | }; 46 | } -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/concepts.ixx: -------------------------------------------------------------------------------- 1 | export module numcpp:concepts; 2 | 3 | import ; 4 | import ; 5 | 6 | namespace numcpp { 7 | template 8 | concept Integral = std::is_integral_v; 9 | 10 | template 11 | concept FloatingPoint = std::is_floating_point_v; 12 | 13 | template 14 | concept Number = Integral || FloatingPoint; 15 | 16 | template 17 | using IteratorMemberFunction = T::iterator(T::*)(); 18 | 19 | template 20 | concept HasBegin = std::is_member_function_pointer_v< 21 | decltype( 22 | IteratorMemberFunction(&T::begin) 23 | ) 24 | >; 25 | 26 | template 27 | concept HasEnd = std::is_member_function_pointer_v< 28 | decltype( 29 | IteratorMemberFunction(&T::end) 30 | ) 31 | >; 32 | 33 | template 34 | concept IsIterable = HasBegin && HasEnd; 35 | 36 | template 37 | concept IsNumberIterable = IsIterable && Number; 38 | 39 | //template 40 | //concept AnyConvertible = std::is_convertible_v || std::is_convertible_v; 41 | 42 | template 43 | concept AnyConvertible = requires { 44 | typename std::common_type_t; 45 | }; 46 | } -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/numcpp.cpp: -------------------------------------------------------------------------------- 1 | export module numcpp; 2 | export import :array; 3 | export import :creation; 4 | export import :algorithm; -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/numcpp.ixx: -------------------------------------------------------------------------------- 1 | export module numcpp; 2 | export import :array; 3 | export import :creation; 4 | export import :algorithm; -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/types.cpp: -------------------------------------------------------------------------------- 1 | export module numcpp:types; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | 8 | namespace numcpp { 9 | using std::size_t; 10 | 11 | export using Shape = std::vector; 12 | 13 | export class SliceItem { 14 | public: 15 | SliceItem(): _isPlaceholder(true) {} 16 | 17 | SliceItem(int32_t value) : _value(value) { 18 | } 19 | 20 | int32_t getValue() const { 21 | return _value; 22 | } 23 | 24 | bool isPlaceholder() const { 25 | return _isPlaceholder; 26 | } 27 | 28 | std::tuple getValidValue(size_t maxSize, bool isStart) const { 29 | int32_t signedMaxSize = static_cast(maxSize); 30 | 31 | if (_isPlaceholder) { 32 | return std::make_tuple(isStart ? 0 : signedMaxSize, true); 33 | } 34 | 35 | if (_value > signedMaxSize) { 36 | return std::make_tuple(signedMaxSize, true); 37 | } 38 | 39 | if (_value < 0) { 40 | int32_t actualValue = maxSize + _value; 41 | 42 | return std::make_tuple(actualValue, actualValue >= 0); 43 | } 44 | 45 | return std::make_tuple(_value, true); 46 | } 47 | 48 | private: 49 | int32_t _value = 0; 50 | bool _isPlaceholder = false; 51 | }; 52 | 53 | export const SliceItem SLICE_PLACEHOLDER; 54 | } 55 | -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/types.ixx: -------------------------------------------------------------------------------- 1 | export module numcpp:types; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | import ; 7 | 8 | namespace numcpp { 9 | export using Shape = std::vector; 10 | 11 | export class SliceItem { 12 | public: 13 | SliceItem(): _isPlaceholder(true) {} 14 | 15 | SliceItem(int32_t value) : _value(value) { 16 | } 17 | 18 | int32_t getValue() const { 19 | return _value; 20 | } 21 | 22 | bool isPlaceholder() const { 23 | return _isPlaceholder; 24 | } 25 | 26 | std::tuple getValidValue(size_t maxSize, bool isStart) const { 27 | int32_t signedMaxSize = static_cast(maxSize); 28 | 29 | if (_isPlaceholder) { 30 | return std::make_tuple(isStart ? 0 : signedMaxSize, true); 31 | } 32 | 33 | if (_value > signedMaxSize) { 34 | return std::make_tuple(signedMaxSize, true); 35 | } 36 | 37 | if (_value < 0) { 38 | int32_t actualValue = maxSize + _value; 39 | 40 | return std::make_tuple(actualValue, actualValue >= 0); 41 | } 42 | 43 | return std::make_tuple(_value, true); 44 | } 45 | 46 | private: 47 | int32_t _value = 0; 48 | bool _isPlaceholder = false; 49 | }; 50 | 51 | export const SliceItem SLICE_PLACEHOLDER; 52 | } -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/utils.cpp: -------------------------------------------------------------------------------- 1 | export module numcpp:utils; 2 | 3 | import :types; 4 | 5 | namespace numcpp { 6 | using std::size_t; 7 | 8 | export size_t calcShapeSize(const Shape& shape) { 9 | if (!shape.size()) { 10 | return 0; 11 | } 12 | 13 | size_t size = 1; 14 | for (size_t axis : shape) { 15 | size *= axis; 16 | } 17 | 18 | return size; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /06/NumCpp/src/numcpp/utils.ixx: -------------------------------------------------------------------------------- 1 | export module numcpp:utils; 2 | 3 | import :types; 4 | 5 | namespace numcpp { 6 | export size_t calcShapeSize(const Shape& shape) { 7 | if (!shape.size()) { 8 | return 0; 9 | } 10 | 11 | size_t size = 1; 12 | for (size_t axis : shape) { 13 | size *= axis; 14 | } 15 | 16 | return size; 17 | } 18 | } -------------------------------------------------------------------------------- /07/01-BasicThread/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 01-BasicThread) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /07/01-BasicThread/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void count(int32_t maxValue) { 6 | int32_t sum = 0; 7 | for (int32_t i = 0; i < maxValue; i++) { 8 | sum += i; 9 | std::cout << "Value: " << i << std::endl; 10 | } 11 | 12 | std::cout << "Sum: " << sum << std::endl; 13 | } 14 | 15 | int main() { 16 | std::thread t(count, 10); // 创建线程对象,将10传递给线程的主执行函数 17 | t.join(); // 等待线程执行结束 18 | std::cout << "Join之后" << std::endl; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /07/02-BasicFileSystem/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 02-BasicFileSystem) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /07/02-BasicFileSystem/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace fs = std::filesystem; 6 | 7 | void createDirectoriesAsync(std::string directoryPath) { 8 | std::cout << "Create directory: " << directoryPath << std::endl; 9 | fs::create_directories(directoryPath); 10 | } 11 | 12 | int main() { 13 | std::cout << "Start task" << std::endl; 14 | 15 | std::thread makeDirTask1(createDirectoriesAsync, "dir1/a/b/c"); 16 | std::thread makeDirTask2(createDirectoriesAsync, "dir2/1/2/3"); 17 | std::thread makeDirTask3(createDirectoriesAsync, "dir3/A/B/C"); 18 | 19 | makeDirTask1.join(); 20 | makeDirTask2.join(); 21 | makeDirTask3.join(); 22 | std::cout << "All task finished" << std::endl; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /07/03-FutureFileSystem/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 03-FutureFileSystem) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /07/03-FutureFileSystem/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace fs = std::filesystem; 7 | 8 | void createDirectoriesAsync( 9 | std::string directoryPath, 10 | std::promise promise 11 | ) { 12 | try { 13 | std::cout << "Create directory: " << directoryPath << std::endl; 14 | bool result = fs::create_directories(directoryPath); 15 | 16 | promise.set_value(result); 17 | } catch (...) { 18 | promise.set_exception(std::current_exception()); 19 | promise.set_value(false); 20 | } 21 | } 22 | 23 | int main() { 24 | std::cout << "Start task" << std::endl; 25 | 26 | std::promise taskPromise1; 27 | std::future taskFuture1 = taskPromise1.get_future(); 28 | std::thread makeDirTask1(createDirectoriesAsync, "dir1/a/b/c", std::move(taskPromise1)); 29 | 30 | std::promise taskPromise2; 31 | std::future taskFuture2 = taskPromise2.get_future(); 32 | std::thread makeDirTask2(createDirectoriesAsync, "dir2/1/2/3", std::move(taskPromise2)); 33 | 34 | std::promise taskPromise3; 35 | std::future taskFuture3 = taskPromise3.get_future(); 36 | std::thread makeDirTask3(createDirectoriesAsync, "dir3/A/B/C", std::move(taskPromise3)); 37 | 38 | taskFuture1.wait(); 39 | taskFuture2.wait(); 40 | taskFuture3.wait(); 41 | 42 | std::cout << "Task1 result: " << taskFuture1.get() << std::endl; 43 | std::cout << "Task2 result: " << taskFuture2.get() << std::endl; 44 | std::cout << "Task3 result: " << taskFuture3.get() << std::endl; 45 | 46 | makeDirTask1.join(); 47 | makeDirTask2.join(); 48 | makeDirTask3.join(); 49 | 50 | std::cout << "All task finished" << std::endl; 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /08/01-PromiseType/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 01-PromiseType) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /08/01-PromiseType/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct promise; 6 | 7 | template 8 | struct Generator : std::coroutine_handle> { 9 | using promise_type = promise; 10 | }; 11 | 12 | template 13 | struct promise { 14 | T _value; 15 | std::exception_ptr _exception; 16 | 17 | template 18 | promise(Ty&& lambdaObj, T value) : _value(value) {} 19 | promise(T value) : _value(value) {} 20 | promise() {} 21 | 22 | Generator get_return_object() { return { Generator::from_promise(*this) }; } 23 | std::suspend_always initial_suspend() noexcept { return {}; } 24 | std::suspend_always final_suspend() noexcept { return {}; } 25 | 26 | std::suspend_always yield_value(T value) { 27 | _value = value; 28 | return {}; 29 | } 30 | 31 | std::suspend_always return_value(T value) { 32 | _value = value; 33 | return {}; 34 | } 35 | void return_void() {} 36 | void unhandled_exception() { _exception = std::current_exception(); } 37 | }; 38 | 39 | int main() { 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /08/02-CoroutineHandle/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 02-CoroutineHandle) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /08/02-CoroutineHandle/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | struct coroutine_handle { 6 | constexpr coroutine_handle() noexcept; 7 | constexpr coroutine_handle(nullptr_t) noexcept; 8 | static coroutine_handle from_promise(Promise&); 9 | coroutine_handle& operator=(nullptr_t) noexcept; 10 | 11 | constexpr void* address() const noexcept; 12 | static constexpr coroutine_handle from_address(void* addr); 13 | 14 | constexpr operator coroutine_handle() const noexcept; 15 | 16 | constexpr explicit operator bool() const noexcept; 17 | bool done() const; 18 | 19 | void operator()() const; 20 | void resume() const; 21 | void destroy() const; 22 | 23 | Promise& promise() const; 24 | 25 | private: 26 | void* ptr; // exposition only 27 | }; 28 | 29 | template<> 30 | struct coroutine_handle { 31 | constexpr coroutine_handle() noexcept; 32 | constexpr coroutine_handle(nullptr_t) noexcept; 33 | coroutine_handle& operator=(nullptr_t) noexcept; 34 | 35 | constexpr void* address() const noexcept; 36 | static constexpr coroutine_handle from_address(void* addr); 37 | 38 | constexpr explicit operator bool() const noexcept; 39 | bool done() const; 40 | 41 | void operator()() const; 42 | void resume() const; 43 | void destroy() const; 44 | 45 | private: 46 | void* ptr; // exposition only 47 | }; 48 | 49 | int main() { 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /08/03-Generator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET 03-Generator) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 12 | add_compile_options(/utf-8) 13 | endif() 14 | 15 | add_executable( 16 | ${TARGET} 17 | src/main.cpp 18 | ) 19 | -------------------------------------------------------------------------------- /08/03-Generator/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct CountGenerator { 6 | struct promise_type { 7 | int32_t _value{ 0 }; 8 | 9 | ~promise_type() { 10 | std::cout << "promise_type destructed" << std::endl; 11 | } 12 | CountGenerator get_return_object() { 13 | return { 14 | ._handle = std::coroutine_handle::from_promise(*this) 15 | }; 16 | } 17 | std::suspend_never initial_suspend() { return {}; } 18 | std::suspend_always final_suspend() noexcept { return {}; } 19 | void unhandled_exception() {} 20 | std::suspend_always yield_value(int32_t value) { 21 | _value = value; 22 | return {}; 23 | } 24 | void return_void() {} 25 | }; 26 | 27 | std::coroutine_handle _handle; 28 | }; 29 | 30 | CountGenerator doCount() { 31 | for (int32_t i = 0; i < 3; ++i) { 32 | co_yield i; 33 | } 34 | } 35 | 36 | int main() { 37 | auto h = doCount()._handle; 38 | auto& promise = h.promise(); 39 | while (!h.done()) { 40 | std::cout << "Count: " << promise._value << std::endl; 41 | h(); 42 | } 43 | h.destroy(); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /08/04-Concepts/src/main.cpp: -------------------------------------------------------------------------------- 1 | // ============= Promise的Concept定义 =================== 2 | // PromiseType是Promise的类型,ValueType是协程中待计算的值的类型 3 | template 4 | concept Promise = requires(PromiseType promise) { 5 | { promise.get_return_object() } -> Coroutine; 6 | { promise.initial_suspend() } -> Awaiter; 7 | { promise.final_suspend() } -> Awaiter; 8 | 9 | requires (requires(ValueType value) { promise.return_value(value); } || { promise.return_void(); }) 10 | { promise.unhandled_exception() }; 11 | }; 12 | 13 | // ============= Awaiter的Concept定义 =================== 14 | // AwaitSuspendResult约束了await_suspend的返回值类型 15 | // AwaiterType是Awaiter的类型,Promise是协程的Promise类型,下同 16 | template 17 | concept AwaitSuspendResult = std::same_as || 18 | std::same_as || 19 | std::same_as>; 20 | 21 | // Awaiter约束定义,Awaiter类型必须满足requires中的所有接口约定 22 | template 23 | concept Awaiter = requires(AwaiterType awaiter, std::coroutine_handle h) { 24 | awaiter.await_resume(); 25 | { awaiter.await_ready() } -> std::same_as; 26 | { awaiter.await_suspend(h) } -> AwaitSuspendResult; 27 | }; 28 | 29 | // ============= Awaitable的Concept定义 =================== 30 | // ValidCoAwait约束用于判断对于AwaitableType是否存在正确的co_await操作符重载 31 | // co_await可以重载为成员函数或者非成员函数,约束中都需要判断 32 | // AwaitableType是Awaitable的类型,Promise是协程的Promise类型,下同 33 | template 34 | concept ValidCoAwait = requires(AwaitableType awaitable) { 35 | { awaitable.operator co_await() } -> Awaiter; 36 | } || requires(AwaitableType awaitable) { 37 | { operator co_await(static_cast(awaitable)) } -> Awaiter; 38 | }; 39 | 40 | // Awaitable约束定义 41 | // Awaitable必须存在正确的co_await操作符重载,或者自身是一个Awaiter 42 | template 43 | concept Awaitable = ValidCoAwait || 44 | Awaiter; 45 | -------------------------------------------------------------------------------- /09_and_10/Asyncpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET NumCpp) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 12 | add_custom_target(std_modules ALL 13 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 14 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint type_traits string filesystem functional coroutine thread chrono mutex vector 15 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 16 | ) 17 | endif() 18 | 19 | function (prepare_for_module TGT) 20 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 21 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 22 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 23 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 24 | add_dependencies(${TGT} std_modules) 25 | endif() 26 | endfunction() 27 | 28 | set (MODULE_EXT cpp) 29 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 30 | set (MODULE_EXT ixx) 31 | add_compile_options(/utf-8) 32 | endif() 33 | 34 | add_executable( 35 | ${TARGET} 36 | src/core/Concepts.${MODULE_EXT} 37 | src/core/Core.${MODULE_EXT} 38 | src/task/AsyncTaskQueue.${MODULE_EXT} 39 | src/task/Coroutine.${MODULE_EXT} 40 | src/task/AsyncTaskLoop.${MODULE_EXT} 41 | src/task/Asyncify.${MODULE_EXT} 42 | src/task/Task.${MODULE_EXT} 43 | src/io/AsyncIoTask.${MODULE_EXT} 44 | src/io/AsyncIoLoop.${MODULE_EXT} 45 | src/io/AsyncIoAsyncify.${MODULE_EXT} 46 | src/io/Io.${MODULE_EXT} 47 | src/fs/FileSystem.${MODULE_EXT} 48 | src/main.cpp 49 | ) 50 | 51 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 52 | prepare_for_module(${TARGET}) 53 | endif() 54 | -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/core/Concepts.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.core:concepts; 2 | 3 | import ; 4 | 5 | namespace asyncpp::core { 6 | export template 7 | concept Invocable = std::is_invocable_v; 8 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/core/Concepts.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.core:concepts; 2 | 3 | import ; 4 | 5 | namespace asyncpp::core { 6 | export template 7 | concept Invocable = std::is_invocable_v; 8 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/core/Core.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.core; 2 | 3 | export import :concepts; -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/core/Core.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.core; 2 | 3 | export import :concepts; -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/fs/FileSystem.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.fs; 2 | 3 | import asyncpp.io; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::fs { 10 | using asyncpp::io::ioAsyncify; 11 | namespace fs = std::filesystem; 12 | 13 | export auto createDirectories(const std::string& directoryPath) { 14 | return ioAsyncify([directoryPath]() { 15 | return fs::create_directories(directoryPath); 16 | }); 17 | } 18 | 19 | export auto exists(const std::string& directoryPath) { 20 | return ioAsyncify([directoryPath]() { 21 | return fs::exists(directoryPath); 22 | }); 23 | } 24 | 25 | export auto removeAll(const std::string& directoryPath) { 26 | return ioAsyncify([directoryPath]() { 27 | return fs::remove_all(directoryPath); 28 | }); 29 | } 30 | 31 | export auto voidFsFunction(const std::string& directoryPath) { 32 | return ioAsyncify([directoryPath]() { 33 | std::cout << directoryPath << std::endl; 34 | }); 35 | } 36 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/fs/FileSystem.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.fs; 2 | 3 | import asyncpp.io; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::fs { 10 | using asyncpp::io::ioAsyncify; 11 | namespace fs = std::filesystem; 12 | 13 | export auto createDirectories(const std::string& directoryPath) { 14 | return ioAsyncify([directoryPath]() { 15 | return fs::create_directories(directoryPath); 16 | }); 17 | } 18 | 19 | export auto exists(const std::string& directoryPath) { 20 | return ioAsyncify([directoryPath]() { 21 | return fs::exists(directoryPath); 22 | }); 23 | } 24 | 25 | export auto removeAll(const std::string& directoryPath) { 26 | return ioAsyncify([directoryPath]() { 27 | return fs::remove_all(directoryPath); 28 | }); 29 | } 30 | 31 | export auto voidFsFunction(const std::string& directoryPath) { 32 | return ioAsyncify([directoryPath]() { 33 | std::cout << directoryPath << std::endl; 34 | }); 35 | } 36 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/AsyncIoLoop.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:loop; 2 | 3 | import :task; 4 | import asyncpp.task; 5 | 6 | import ; 7 | import ; 8 | import ; 9 | 10 | namespace asyncpp::io { 11 | export class AsyncIoLoop { 12 | public: 13 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 14 | static const int32_t SLEEP_MS = 1000; 15 | 16 | static AsyncIoLoop& start(); 17 | 18 | private: 19 | // 支持单例模式,将其定义未private,防止外部调用构造函数 20 | AsyncIoLoop() { 21 | _thread = std::jthread(std::bind(&AsyncIoLoop::loopMain, this)); 22 | } 23 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 24 | AsyncIoLoop(const AsyncIoLoop&) = delete; 25 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 26 | AsyncIoLoop& operator=(const AsyncIoLoop&) = delete; 27 | 28 | void loopExecution() { 29 | AsyncIoTask opItem; 30 | if (!AsyncIoTaskQueue::getInstance().dequeue(&opItem)) { 31 | return; 32 | } 33 | 34 | opItem.taskHandler(); 35 | 36 | auto& asyncEventQueue = asyncpp::task::AsyncTaskQueue::getInstance(); 37 | asyncEventQueue.enqueue({ 38 | .handler = opItem.resumeHandler 39 | }); 40 | } 41 | 42 | void loopMain() { 43 | while (true) { 44 | loopExecution(); 45 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 46 | } 47 | } 48 | 49 | // jthread对象,为I/O线程,jthread让该线程结束之前整个进程都不会结束 50 | std::jthread _thread; 51 | }; 52 | 53 | AsyncIoLoop& AsyncIoLoop::start() { 54 | static AsyncIoLoop ioLoop; 55 | 56 | return ioLoop; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/AsyncIoLoop.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:loop; 2 | 3 | import :task; 4 | import asyncpp.task; 5 | 6 | import ; 7 | import ; 8 | import ; 9 | import ; 10 | 11 | namespace asyncpp::io { 12 | export class AsyncIoLoop { 13 | public: 14 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 15 | static const int32_t SLEEP_MS = 1000; 16 | 17 | static AsyncIoLoop& start(); 18 | 19 | private: 20 | // 支持单例模式,将其定义未private,防止外部调用构造函数 21 | AsyncIoLoop() { 22 | _thread = std::jthread(std::bind(&AsyncIoLoop::loopMain, this)); 23 | } 24 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 25 | AsyncIoLoop(const AsyncIoLoop&) = delete; 26 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 27 | AsyncIoLoop& operator=(const AsyncIoLoop&) = delete; 28 | 29 | void loopExecution() { 30 | AsyncIoTask opItem; 31 | if (!AsyncIoTaskQueue::getInstance().dequeue(&opItem)) { 32 | return; 33 | } 34 | 35 | opItem.taskHandler(); 36 | 37 | auto& asyncEventQueue = asyncpp::task::AsyncTaskQueue::getInstance(); 38 | asyncEventQueue.enqueue({ 39 | .handler = opItem.resumeHandler 40 | }); 41 | } 42 | 43 | void loopMain() { 44 | while (true) { 45 | loopExecution(); 46 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 47 | } 48 | } 49 | 50 | // jthread对象,为I/O线程,jthread让该线程结束之前整个进程都不会结束 51 | std::jthread _thread; 52 | }; 53 | 54 | AsyncIoLoop& AsyncIoLoop::start() { 55 | static AsyncIoLoop ioLoop; 56 | 57 | return ioLoop; 58 | } 59 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/AsyncIoTask.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:task; 2 | 3 | import asyncpp.core; 4 | import asyncpp.task; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::io { 10 | 11 | export struct AsyncIoTask { 12 | using ResumeHandler = std::function; 13 | using TaskHandler = std::function; 14 | 15 | // 协程唤醒函数 16 | ResumeHandler resumeHandler; 17 | // I/O任务函数 18 | TaskHandler taskHandler; 19 | }; 20 | 21 | export class AsyncIoTaskQueue { 22 | public: 23 | static AsyncIoTaskQueue& getInstance(); 24 | 25 | void enqueue(const AsyncIoTask& item) { 26 | std::lock_guard guard(_queueMutex); 27 | 28 | _queue.push_back(item); 29 | } 30 | 31 | bool dequeue(AsyncIoTask* item) { 32 | std::lock_guard guard(_queueMutex); 33 | 34 | if (_queue.size() == 0) { 35 | return false; 36 | } 37 | 38 | *item = _queue.back(); 39 | _queue.pop_back(); 40 | 41 | return true; 42 | } 43 | 44 | size_t getSize() const { 45 | return _queue.size(); 46 | } 47 | 48 | private: 49 | // I/O任务队列 50 | std::vector _queue; 51 | // I/O任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 52 | std::mutex _queueMutex; 53 | }; 54 | 55 | AsyncIoTaskQueue& AsyncIoTaskQueue::getInstance() { 56 | static AsyncIoTaskQueue queue; 57 | 58 | return queue; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/AsyncIoTask.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:task; 2 | 3 | import asyncpp.core; 4 | import asyncpp.task; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::io { 10 | 11 | export struct AsyncIoTask { 12 | using ResumeHandler = std::function; 13 | using TaskHandler = std::function; 14 | 15 | // 协程唤醒函数 16 | ResumeHandler resumeHandler; 17 | // I/O任务函数 18 | TaskHandler taskHandler; 19 | }; 20 | 21 | export class AsyncIoTaskQueue { 22 | public: 23 | static AsyncIoTaskQueue& getInstance(); 24 | 25 | void enqueue(const AsyncIoTask& item) { 26 | std::lock_guard guard(_queueMutex); 27 | 28 | _queue.push_back(item); 29 | } 30 | 31 | bool dequeue(AsyncIoTask* item) { 32 | std::lock_guard guard(_queueMutex); 33 | 34 | if (_queue.size() == 0) { 35 | return false; 36 | } 37 | 38 | *item = _queue.back(); 39 | _queue.pop_back(); 40 | 41 | return true; 42 | } 43 | 44 | size_t getSize() const { 45 | return _queue.size(); 46 | } 47 | 48 | private: 49 | // I/O任务队列 50 | std::vector _queue; 51 | // I/O任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 52 | std::mutex _queueMutex; 53 | }; 54 | 55 | AsyncIoTaskQueue& AsyncIoTaskQueue::getInstance() { 56 | static AsyncIoTaskQueue queue; 57 | 58 | return queue; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/Io.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io; 2 | 3 | export import :loop; 4 | export import :task; 5 | export import :asyncify; -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/io/Io.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io; 2 | 3 | export import :loop; 4 | export import :task; 5 | export import :asyncify; -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/AsyncTaskLoop.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:loop; 2 | 3 | import :queue; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export class AsyncTaskLoop { 10 | public: 11 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 12 | static const int32_t SLEEP_MS = 1000; 13 | 14 | static AsyncTaskLoop& getInstance(); 15 | static void start() { 16 | getInstance().startLoop(); 17 | } 18 | 19 | private: 20 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 21 | AsyncTaskLoop() = default; 22 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 23 | AsyncTaskLoop(const AsyncTaskLoop&) = delete; 24 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 25 | AsyncTaskLoop& operator=(const AsyncTaskLoop&) = delete; 26 | 27 | void startLoop() { 28 | while (true) { 29 | loopExecution(); 30 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 31 | } 32 | } 33 | 34 | void loopExecution() { 35 | AsyncTask asyncEvent; 36 | if (!AsyncTaskQueue::getInstance().dequeue(&asyncEvent)) { 37 | return; 38 | } 39 | 40 | asyncEvent.handler(); 41 | } 42 | }; 43 | 44 | AsyncTaskLoop& AsyncTaskLoop::getInstance() { 45 | static AsyncTaskLoop eventLoop; 46 | 47 | return eventLoop; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/AsyncTaskLoop.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:loop; 2 | 3 | import :queue; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export class AsyncTaskLoop { 10 | public: 11 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 12 | static const int32_t SLEEP_MS = 1000; 13 | 14 | static AsyncTaskLoop& getInstance(); 15 | static void start() { 16 | getInstance().startLoop(); 17 | } 18 | 19 | private: 20 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 21 | AsyncTaskLoop() = default; 22 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 23 | AsyncTaskLoop(const AsyncTaskLoop&) = delete; 24 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 25 | AsyncTaskLoop& operator=(const AsyncTaskLoop&) = delete; 26 | 27 | void startLoop() { 28 | while (true) { 29 | loopExecution(); 30 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 31 | } 32 | } 33 | 34 | void loopExecution() { 35 | AsyncTask asyncEvent; 36 | if (!AsyncTaskQueue::getInstance().dequeue(&asyncEvent)) { 37 | return; 38 | } 39 | 40 | asyncEvent.handler(); 41 | } 42 | }; 43 | 44 | AsyncTaskLoop& AsyncTaskLoop::getInstance() { 45 | static AsyncTaskLoop eventLoop; 46 | 47 | return eventLoop; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/AsyncTaskQueue.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:queue; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export struct AsyncTask { 10 | // 异步任务处理函数类型 11 | using Handler = std::function; 12 | 13 | // 异步任务处理函数 14 | Handler handler; 15 | }; 16 | 17 | export class AsyncTaskQueue { 18 | public: 19 | static AsyncTaskQueue& getInstance(); 20 | 21 | void enqueue(const AsyncTask& item) { 22 | std::lock_guard guard(_queueMutex); 23 | 24 | _queue.push_back(item); 25 | } 26 | 27 | bool dequeue(AsyncTask* item) { 28 | std::lock_guard guard(_queueMutex); 29 | 30 | if (_queue.size() == 0) { 31 | return false; 32 | } 33 | 34 | *item = _queue.back(); 35 | _queue.pop_back(); 36 | 37 | return true; 38 | } 39 | 40 | size_t getSize() const { 41 | return _queue.size(); 42 | } 43 | 44 | private: 45 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 46 | AsyncTaskQueue() = default; 47 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 48 | AsyncTaskQueue(const AsyncTaskQueue&) = delete; 49 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 50 | AsyncTaskQueue& operator=(const AsyncTaskQueue&) = delete; 51 | 52 | // 异步任务队列 53 | std::vector _queue; 54 | // 异步任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 55 | std::mutex _queueMutex; 56 | }; 57 | 58 | AsyncTaskQueue& AsyncTaskQueue::getInstance() { 59 | static AsyncTaskQueue queue; 60 | 61 | return queue; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/AsyncTaskQueue.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:queue; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export struct AsyncTask { 10 | // 异步任务处理函数类型 11 | using Handler = std::function; 12 | 13 | // 异步任务处理函数 14 | Handler handler; 15 | }; 16 | 17 | export class AsyncTaskQueue { 18 | public: 19 | static AsyncTaskQueue& getInstance(); 20 | 21 | void enqueue(const AsyncTask& item) { 22 | std::lock_guard guard(_queueMutex); 23 | 24 | _queue.push_back(item); 25 | } 26 | 27 | bool dequeue(AsyncTask* item) { 28 | std::lock_guard guard(_queueMutex); 29 | 30 | if (_queue.size() == 0) { 31 | return false; 32 | } 33 | 34 | *item = _queue.back(); 35 | _queue.pop_back(); 36 | 37 | return true; 38 | } 39 | 40 | size_t getSize() const { 41 | return _queue.size(); 42 | } 43 | 44 | private: 45 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 46 | AsyncTaskQueue() = default; 47 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 48 | AsyncTaskQueue(const AsyncTaskQueue&) = delete; 49 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 50 | AsyncTaskQueue& operator=(const AsyncTaskQueue&) = delete; 51 | 52 | // 异步任务队列 53 | std::vector _queue; 54 | // 异步任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 55 | std::mutex _queueMutex; 56 | }; 57 | 58 | AsyncTaskQueue& AsyncTaskQueue::getInstance() { 59 | static AsyncTaskQueue queue; 60 | 61 | return queue; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/Task.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task; 2 | 3 | export import :queue; 4 | export import :loop; 5 | export import :coroutine; 6 | export import :asyncify; -------------------------------------------------------------------------------- /09_and_10/Asyncpp/src/task/Task.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task; 2 | 3 | export import :queue; 4 | export import :loop; 5 | export import :coroutine; 6 | export import :asyncify; -------------------------------------------------------------------------------- /11_and_12/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch11) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 9 | add_compile_options(/utf-8) 10 | endif() 11 | 12 | add_executable( 13 | 01-STLSample 14 | Projects/01-STLSample/src/main.cpp 15 | ) 16 | 17 | add_executable( 18 | 02-RangesSample 19 | Projects/02-RangesSample/src/main.cpp 20 | ) 21 | 22 | add_executable( 23 | 03-RangesIteratorSample 24 | Projects/03-RangesIteratorSample/src/main.cpp 25 | ) 26 | 27 | add_executable( 28 | 04-RangesSizeSample 29 | Projects/04-RangesSizeSample/src/main.cpp 30 | ) 31 | 32 | add_executable( 33 | 05-RangesDataSample 34 | Projects/05-RangesDataSample/src/main.cpp 35 | ) 36 | 37 | add_executable( 38 | 06-RangesDanglingFailed 39 | Projects/06-RangesDanglingFailed/src/main.cpp 40 | ) 41 | 42 | add_executable( 43 | 07-RangesDanglingCheck 44 | Projects/07-RangesDanglingCheck/src/main.cpp 45 | ) 46 | 47 | add_executable( 48 | 08-ViewBasic 49 | Projects/08-ViewBasic/src/main.cpp 50 | ) 51 | 52 | add_executable( 53 | 09-ArrayView 54 | Projects/09-ArrayView/src/main.cpp 55 | ) 56 | 57 | add_executable( 58 | 10-FactorySample 59 | Projects/10-FactorySample/src/main.cpp 60 | ) 61 | 62 | add_executable( 63 | 11-AdaptorSample 64 | Projects/11-AdaptorSample/src/main.cpp 65 | ) 66 | 67 | add_executable( 68 | 12-STLRandom 69 | Projects/12-STLRandom/src/main.cpp 70 | ) 71 | 72 | add_executable( 73 | 13-PipelineSample 74 | Projects/13-PipelineSample/src/main.cpp 75 | ) 76 | -------------------------------------------------------------------------------- /11_and_12/Projects/01-STLSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | std::vector numbers{ 8 | 1, 2, 3, 4, 5 9 | }; 10 | 11 | std::vector doubledNumbers; 12 | std::transform( 13 | numbers.begin(), numbers.end(), std::back_inserter(doubledNumbers), 14 | [](int32_t number) { return number * 2; } 15 | ); 16 | 17 | std::vector filteredNumbers; 18 | std::copy_if( 19 | doubledNumbers.begin(), doubledNumbers.end(), std::back_inserter(filteredNumbers), 20 | [](int32_t number) { return number < 5; } 21 | ); 22 | 23 | std::for_each(filteredNumbers.begin(), filteredNumbers.end(), [](int32_t number) { 24 | std::cout << number << std::endl; 25 | }); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /11_and_12/Projects/02-RangesSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | namespace ranges = std::ranges; 9 | namespace views = std::views; 10 | 11 | std::vector numbers{ 12 | 1, 2, 3, 4, 5 13 | }; 14 | 15 | ranges::for_each(numbers | 16 | views::transform([](int32_t number) { return number * 2; }) | 17 | views::filter([](int32_t number) { return number < 5; }), 18 | [](int32_t number) { 19 | std::cout << number << std::endl; 20 | } 21 | ); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /11_and_12/Projects/03-RangesIteratorSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | namespace ranges = std::ranges; 8 | 9 | // 首先,调用ranges::begin和ranges::end函数获取容器的迭代器 10 | // 接着,通过迭代器访问数据中的元素 11 | std::vector v = { 3, 1, 4, 1, 5, 9, 2, 6 }; 12 | auto start = ranges::begin(v); 13 | std::cout << "[0]: " << *start << std::endl; 14 | 15 | auto curr = start; 16 | curr++; 17 | std::cout << "[1]: " << *curr << std::endl; 18 | 19 | std::cout << "[5]: " << *(curr + 3) << std::endl; 20 | 21 | auto stop = ranges::end(v); 22 | std::sort(start, stop); 23 | 24 | // 最后,调用ranges::cbegin和ranges::cend循环输出排序后的数据 25 | for (auto it = ranges::cbegin(v); 26 | it != ranges::cend(v); 27 | ++it 28 | ) { 29 | std::cout << *it << " "; 30 | } 31 | std::cout << std::endl; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /11_and_12/Projects/04-RangesSizeSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | namespace ranges = std::ranges; 7 | 8 | std::vector v = { 3, 1, 4, 1, 5, 9, 2, 6 }; 9 | std::cout << ranges::size(v) << std::endl; 10 | std::cout << ranges::ssize(v) << std::endl; 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /11_and_12/Projects/05-RangesDataSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | namespace ranges = std::ranges; 7 | 8 | std::vector v = { 3, 1, 4, 1, 5, 9, 2, 6 }; 9 | 10 | auto data = ranges::data(v); 11 | std::cout << "[1]" << data[1] << std::endl; 12 | data[2] = 10; 13 | 14 | auto cdata = ranges::cdata(v); 15 | std::cout << "[2]" << cdata[2] << std::endl; 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /11_and_12/Projects/06-RangesDanglingFailed/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | namespace ranges = std::ranges; 8 | 9 | auto getArray = [] { return std::vector{ 0, 1, 0, 1 }; }; 10 | 11 | // 编译成功 12 | auto start = std::find(getArray().begin(), getArray().end(), 1); 13 | std::cout << *start << std::endl; 14 | 15 | // 编译失败 16 | // auto rangeStart = ranges::find(getArray(), 1); 17 | // std::cout << *rangeStart << std::endl; 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /11_and_12/Projects/07-RangesDanglingCheck/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | namespace ranges = std::ranges; 8 | 9 | auto getArray = [] { return std::vector{ 0, 1, 0, 1 }; }; 10 | 11 | auto rangeStart = ranges::find(getArray(), 1); 12 | // 通过type_traits在运行时检测返回的迭代器是否为悬空迭代器(不会引发编译错误) 13 | std::cout << std::is_same_v << std::endl; 14 | 15 | // 通过static_assert主动提供容易理解的编译期错误(会引发编译错误!!!) 16 | // static_assert(!std::is_same_v, "rangeStart is dangling!!!!"); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /11_and_12/Projects/08-ViewBasic/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | for (int32_t i : std::views::iota(1) | std::views::take(4)) { 7 | std::cout << i << " "; 8 | } 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /11_and_12/Projects/09-ArrayView/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | class ArrayView : public std::ranges::view_interface> { 8 | public: 9 | using Container = std::array; 10 | 11 | ArrayView() = default; 12 | ArrayView(const Container& container) : 13 | _begin(container.cbegin()), _end(container.cend()) 14 | {} 15 | 16 | auto begin() const { 17 | return _begin; 18 | } 19 | 20 | auto end() const { 21 | return _end; 22 | } 23 | 24 | private: 25 | typename Container::const_iterator _begin; 26 | typename Container::const_iterator _end; 27 | }; 28 | 29 | int main() { 30 | std::array array = { 1, 2, 3, 4 }; 31 | ArrayView arrayView { array }; 32 | 33 | for (auto v : arrayView) { 34 | std::cout << v << " "; 35 | } 36 | std::cout << std::endl; 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /11_and_12/Projects/10-FactorySample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | namespace ranges = std::ranges; 8 | namespace views = std::views; 9 | 10 | // iota_view与iota 11 | for (int32_t i : ranges::iota_view{ 0, 10 }) { 12 | std::cout << i << " "; 13 | } 14 | std::cout << std::endl; 15 | 16 | for (int32_t i : views::iota(1) | views::take(4)) { 17 | std::cout << i << " "; 18 | } 19 | std::cout << std::endl; 20 | 21 | // istream_view与istream 22 | std::istringstream textStream{ "hello, world" }; 23 | for (const std::string& s : ranges::istream_view{ textStream }) { 24 | std::cout << "Text: " << s << std::endl; 25 | } 26 | 27 | std::istringstream numberStream{ "3 1 4 1 5" }; 28 | for (int n : views::istream(numberStream)) { 29 | std::cout << "Number: " << n << std::endl; 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /11_and_12/Projects/11-AdaptorSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | namespace ranges = std::ranges; 9 | namespace views = std::views; 10 | 11 | std::random_device rd; 12 | std::mt19937 gen(rd()); 13 | std::uniform_int_distribution<> distrib(1, 10); 14 | 15 | // 步骤6:输出 16 | ranges::for_each( 17 | // 步骤5:将键值对序列[(0,a1),(1,a2),...,(n, an)]转换为[0+a1,1+a2,...,n+an]的求和序列 18 | views::transform( 19 | // 步骤4:选取结果键值对的至多前3个键值对(不足3个则全部返回) 20 | views::take( 21 | // 步骤3:从随机数键值对中筛选数值大于5的键值对 22 | views::filter( 23 | // 步骤2:生成随机数键值对序列[(0,a1),(1,a2),...,(n, an)] 24 | views::transform( 25 | // 步骤1:生成序列[0,10) 26 | views::iota(0, 10), 27 | [&distrib, &gen](auto index) { return std::make_pair(index, distrib(gen)); } 28 | ), 29 | [](auto element) { return element.second > 5; } 30 | ), 31 | 3 32 | ), 33 | [](auto element) { return element.first + element.second; } 34 | ), 35 | [](auto number) { 36 | std::cout << number << " "; 37 | } 38 | ); 39 | std::cout << std::endl; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /11_and_12/Projects/12-STLRandom/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | std::random_device rd; 9 | std::mt19937 gen(rd()); 10 | std::uniform_int_distribution<> distrib(1, 10); 11 | 12 | std::vector rangeNumbers(10, 0); 13 | std::iota(rangeNumbers.begin(), rangeNumbers.end(), 0); 14 | 15 | std::vector> rangePairs; 16 | std::transform(rangeNumbers.begin(), rangeNumbers.end(), std::back_inserter(rangePairs), [&distrib, &gen](int index) { 17 | return std::make_pair(index, distrib(gen)); 18 | }); 19 | 20 | std::vector> filteredPairs; 21 | std::copy_if(rangePairs.begin(), rangePairs.end(), std::back_inserter(filteredPairs), [](const auto& element) { 22 | return element.second > 5; 23 | }); 24 | 25 | std::vector> leadingPairs; 26 | std::copy_n(filteredPairs.begin(), 3, std::back_inserter(leadingPairs)); 27 | 28 | std::vector resultNumbers; 29 | std::transform(leadingPairs.begin(), leadingPairs.end(), std::back_inserter(resultNumbers), [](const auto& element) { 30 | return element.first + element.second; 31 | }); 32 | 33 | std::for_each(resultNumbers.begin(), resultNumbers.end(), [](int number) { 34 | std::cout << number << " "; 35 | }); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /11_and_12/Projects/13-PipelineSample/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | namespace ranges = std::ranges; 9 | namespace views = std::views; 10 | 11 | std::random_device rd; 12 | std::mt19937 gen(rd()); 13 | std::uniform_int_distribution<> distrib(1, 10); 14 | 15 | ranges::for_each( 16 | views::iota(0, 10) | 17 | views::transform([&distrib, &gen](int index) { return std::make_pair(index, distrib(gen)); }) | 18 | views::filter([](const auto& element) { return element.second > 5; }) | 19 | views::take(3) | 20 | views::transform([](const auto& element) { return element.first + element.second; }), 21 | [](int number) { 22 | std::cout << number << " "; 23 | } 24 | ); 25 | std::cout << std::endl; 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /13/include/ca/IoUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | std::ostream& operator<<( 7 | std::ostream& os, 8 | const ca::types::ChoosedModelObjectTableData& choosedModelObjectTableData 9 | ); -------------------------------------------------------------------------------- /13/include/ca/RangeUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace ca::utils { 8 | // 获取range的size(针对无法使用ssize的range) 9 | template 10 | size_t sizeOfRange( 11 | T& range 12 | ) { 13 | return static_cast(std::accumulate( 14 | range.begin(), 15 | range.end(), 16 | 0, 17 | [](int32_t prev, const auto& value) { return prev + 1; } 18 | )); 19 | } 20 | 21 | // 所有的自定义视图和“仿视图”都定义在这里 22 | namespace views { 23 | // |操作符重载所需的一个类型占位符,每个想要放入视图管道的“仿视图”都需要定义一个 24 | template 25 | struct ToFn { 26 | }; 27 | 28 | // Range适配器对象的生成函数,返回ToFn对象 29 | template 30 | ToFn to() { 31 | return ToFn(); 32 | } 33 | 34 | // 操作符|重载。左侧参数是一个视图Range,右侧参数是类型占位符ToFn 35 | template 36 | Container operator | (Range range, const ToFn& fn) { 37 | // 构造容器对象,并调用copy将range中的数据复制到容器中 38 | Container container{}; 39 | std::ranges::copy(range, std::back_inserter(container)); 40 | 41 | return container; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /13/include/ca/TimeUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | 5 | namespace ca::utils { 6 | 7 | ca::types::ZonedTime timePointFromString(const std::string& timeString); 8 | 9 | } -------------------------------------------------------------------------------- /13/include/ca/algorithms/FunctionalAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | #include 6 | 7 | namespace ca::algorithms::functional { 8 | using ModelObjectOutputIterator = std::back_insert_iterator>; 9 | 10 | void parseModelObjectTableData( 11 | // 模型视图begin迭代器 12 | std::vector::const_iterator modelViewsBegin, 13 | // 模型视图end迭代器 14 | std::vector::const_iterator modelViewsEnd, 15 | // 高精度对象集合 16 | const std::set& highResolutionObjectSet, 17 | // 三角面片数上限 18 | int32_t meshCount, 19 | // 低精度对象输出迭代器,用于输出插入低精度对象 20 | ModelObjectOutputIterator lowResolutionObjectOutputIterator, 21 | // 高精度对象输出迭代器,用于输出插入高精度对象 22 | ModelObjectOutputIterator highResolutionObjectOutputIterator 23 | ); 24 | } -------------------------------------------------------------------------------- /13/include/ca/algorithms/ProcedureAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | namespace ca::algorithms::procedure { 7 | ca::types::ModelObjectTableData parseModelObjectTableData( 8 | // 模型视图数据 9 | std::vector modelViews, 10 | // 高精度对象集合 11 | const std::set& highResolutionObjectSet, 12 | // 三角面片数上限 13 | int32_t meshCount 14 | ); 15 | } -------------------------------------------------------------------------------- /13/include/ca/algorithms/RangesAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | namespace ca::algorithms::ranges { 7 | ca::types::ModelObjectTableData parseModelObjectTableData( 8 | // 模型视图数据 9 | std::vector modelViews, 10 | // 高精度对象集合 11 | const std::set& highResolutionObjectSet, 12 | // 三角面片数上限 13 | int32_t meshCount 14 | ); 15 | } -------------------------------------------------------------------------------- /13/include/data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | #include 6 | #include 7 | 8 | struct ModelObjectsInfo { 9 | // 模型视图数据列表 10 | std::vector modelViews; 11 | // 高精度对象集合 12 | std::set highResolutionObjectSet; 13 | // 3D模型可用三角面片总数 14 | int32_t meshCount; 15 | }; 16 | 17 | ModelObjectsInfo getModelObjectsInfo(); -------------------------------------------------------------------------------- /13/src/ca/TimeUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ca/TimeUtils.h" 2 | 3 | namespace ca::utils { 4 | 5 | ca::types::ZonedTime timePointFromString(const std::string& timeString) { 6 | namespace chrono = std::chrono; 7 | 8 | constexpr std::string_view TIME_LOCATION = "Asia/Shanghai"; 9 | constexpr std::string_view TIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z"; 10 | 11 | // 根据用户输入的字符串创建一个istringstream对象,作为时间文本解析的输入流 12 | chrono::time_point specifiedTimePoint; 13 | std::istringstream timeStringStream(timeString); 14 | 15 | // 调用chrono的from_stream函数,从字符串流中读取文本,按照TIME_FORMAT格式进行解析,解析后的时间存储在specifiedTimePoint中。 16 | chrono::from_stream( 17 | timeStringStream, 18 | TIME_FORMAT.data(), 19 | specifiedTimePoint 20 | ); 21 | 22 | // 按照时间字符串中的时区和解析得到的time_point构造zoned_time对象 23 | std::chrono::zoned_time zonedSpecifiedTimePoint { 24 | TIME_LOCATION, 25 | specifiedTimePoint 26 | }; 27 | 28 | return zonedSpecifiedTimePoint; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /14/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch14) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 9 | add_compile_options(/utf-8) 10 | endif() 11 | 12 | add_executable( 13 | 01-SimpleLog 14 | Projects/01-SimpleLog/src/main.cpp 15 | ) 16 | 17 | add_executable( 18 | 02-FormatTo 19 | Projects/02-FormatTo/src/main.cpp 20 | ) 21 | 22 | add_executable( 23 | 03-VFormat 24 | Projects/03-VFormat/src/main.cpp 25 | ) 26 | 27 | add_executable( 28 | 04-Formatter 29 | Projects/04-Formatter/src/main.cpp 30 | ) 31 | -------------------------------------------------------------------------------- /14/Projects/01-SimpleLog/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // 使用 std::chrono 来打印日志的时间 8 | using TimePoint = std::chrono::time_point; 9 | 10 | struct HttpLogParams { 11 | std::string user; 12 | TimePoint requestTime; // C++20 提供了chrono对format的支持 13 | std::string level; 14 | std::string ip; 15 | std::string method; 16 | std::string path; 17 | std::string httpVersion; 18 | int32_t statusCode; 19 | int32_t bodySize; 20 | std::string refer; 21 | std::string agent; 22 | }; 23 | 24 | void formatOutputParams(const HttpLogParams& params); 25 | 26 | int main() { 27 | HttpLogParams logParams = { 28 | .user = "www", 29 | .requestTime = std::chrono::system_clock::now(), 30 | .level = "INFO", 31 | .ip = "127.0.0.1", 32 | .method = "GET", 33 | .path = "/api/v1/info", 34 | .httpVersion = "HTTP/1.0", 35 | .statusCode = 200, 36 | .bodySize = 6934, 37 | .refer = "http://127.0.0.1/index.hmtl", 38 | .agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0", 39 | }; 40 | 41 | formatOutputParams(logParams); 42 | 43 | return 0; 44 | } 45 | 46 | void formatOutputParams(const HttpLogParams& params) { 47 | std::string logLine = std::format("{0:<16}|{1:%Y-%m-%d}T{1:%H:%M:%OS}Z {2} {3} - \"{4} {5} {6}\" {7} {8} \"{9}\" \"{10}\"", 48 | params.user, 49 | params.requestTime, 50 | params.level, 51 | params.ip, 52 | params.method, 53 | params.path, 54 | params.httpVersion, 55 | params.statusCode, 56 | params.bodySize, 57 | params.refer, 58 | params.agent 59 | ); 60 | 61 | std::cout << logLine << std::endl; 62 | } -------------------------------------------------------------------------------- /14/Projects/02-FormatTo/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | // format_to 7 | // 将生成的文本输出到一个输出迭代器中, 8 | // 其他与format一致,这样可以兼容标准STL算法函数的风格, 9 | // 也便于将文本输出到其他的流中或者自建的字符串类中。 10 | std::string resultLine1; 11 | std::format_to(std::back_inserter(resultLine1), "{} + {} = {}", 1, 2, 1 + 2); 12 | std::cout << resultLine1 << std::endl; 13 | 14 | // format_to_n 15 | // 将生成的文本输出到一个输出迭代器中,同时指定输出的最大字符数量。 16 | // 其他与format一致,相当于format_to的扩展版本, 17 | // 在输出目标有字符限制的时候非常有效。 18 | std::string resultLine2(5, ' '); 19 | std::format_to_n(resultLine2.begin(), 5, "{} + {} = {}", 1, 2, 1 + 2); 20 | std::cout << resultLine2 << std::endl; 21 | 22 | // formatted_sizes 23 | // 获取生成文本的长度,参数与format完全一致。 24 | // 25 | auto resultSize = std::formatted_size("{} + {} = {}", 1, 2, 1 + 2); 26 | std::cout << resultSize << std::endl; 27 | 28 | std::string resultLine3(resultSize, ' '); 29 | std::format_to(resultLine3.begin(), "{} + {} = {}", 1, 2, 1 + 2); 30 | std::cout << resultLine3 << std::endl; 31 | } -------------------------------------------------------------------------------- /14/Projects/03-VFormat/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | std::string resultLine1 = std::vformat("{} * {} = {}", std::make_format_args( 8 | 3, 4, 3 * 4 9 | )); 10 | std::cout << resultLine1 << std::endl; 11 | 12 | std::format_args args = std::make_format_args( 13 | 3, 4, 3 * 4 14 | ); 15 | 16 | std::string resultLine2; 17 | std::vformat_to(std::back_inserter(resultLine2), "{} * {} = {}", args); 18 | std::cout << resultLine2 << std::endl; 19 | } -------------------------------------------------------------------------------- /14/Projects/04-Formatter/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | struct std::formatter, CharT> : std::formatter { 8 | template 9 | auto format(std::vector t, FormatContext& fc) const { 10 | auto it = std::formatter::format(t.size(), fc); 11 | 12 | for (int32_t v : t) { 13 | *it = ' '; 14 | it++; 15 | 16 | it = std::formatter::format(v, fc); 17 | } 18 | 19 | return it; 20 | } 21 | }; 22 | 23 | int main() { 24 | std::vector v = { 1, 2, 3, 4 }; 25 | 26 | // 首先,调用format输出vector的长度, 27 | // 然后遍历vector,每次输出一个空格后再调用format输出数字。 28 | std::cout << std::format("{:#x}", v); 29 | } -------------------------------------------------------------------------------- /15/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch14) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 9 | add_compile_options(/utf-8) 10 | endif() 11 | 12 | function (add_deps TGT) 13 | target_include_directories( 14 | ${TGT} 15 | PRIVATE 16 | Projects/logger/include 17 | ) 18 | endfunction() 19 | 20 | add_library( 21 | logging 22 | Projects/logger/src/logging/formatters/CFormatter.cpp 23 | Projects/logger/src/logging/formatters/ModernFormatter.cpp 24 | Projects/logger/src/logging/formatters/StreamFormatter.cpp 25 | ) 26 | target_sources( 27 | logging 28 | PRIVATE 29 | Projects/logger/include/logging/Formatter.h 30 | Projects/logger/include/logging/Handler.h 31 | Projects/logger/include/logging/Level.h 32 | Projects/logger/include/logging/Logger.h 33 | Projects/logger/include/logging/Record.h 34 | Projects/logger/include/logging/formatters/CFormatter.h 35 | Projects/logger/include/logging/formatters/ModernFormatter.h 36 | Projects/logger/include/logging/formatters/StreamFormatter.h 37 | Projects/logger/include/logging/handlers/DefaultHandler.h 38 | Projects/logger/include/logging/handlers/FileHandler.h 39 | Projects/logger/include/logging/handlers/StreamHandler.h 40 | ) 41 | add_deps(logging) 42 | 43 | add_executable( 44 | sample 45 | Projects/sample/src/main.cpp 46 | ) 47 | add_deps(sample) 48 | target_link_libraries(sample logging) 49 | -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/Formatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Record.h" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace logging { 9 | // Formatter类型,所有将日志记录转换成字符串的函数/仿函数和Lambda都可以作为Formatter 10 | using Formatter = std::function; 11 | 12 | // defaultFormatter:默认格式化器 13 | inline std::string defaultFormatter(const Record& record) { 14 | // 调用format返回简单的日志信息 15 | return std::format("{}:{}:{}", record.getLevelName(), record.name, record.message); 16 | } 17 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/Handler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Formatter.h" 4 | #include "logging/Level.h" 5 | #include "logging/Record.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace logging { 12 | // Handler Concept 13 | // 不强制所有Handler都继承BaseHandler,只需要满足特定的接口,因此定义Concept 14 | template 15 | concept Handler = requires (HandlerType handler, const Record & record, Level level) { 16 | // 要求有emit成员函数 17 | handler.template emit(record); 18 | // 要求有format函数,可以将Record对象格式化为string类型的字符串 19 | { handler.format(record) } -> std::same_as; 20 | // 要求有移动构造函数,无拷贝构造函数 21 | }&& std::move_constructible && !std::copy_constructible; 22 | 23 | // BaseHandler类定义 24 | // HandlerLevel是日志处理器的日志等级 25 | // 自己实现Handler时可以继承BaseHandler然后实现emit 26 | template 27 | class BaseHandler { 28 | public: 29 | // 构造函数:formatter为日志处理器的格式化器 30 | BaseHandler(Formatter formatter) : _formatter(formatter) {} 31 | 32 | // 不允许拷贝 33 | BaseHandler(const BaseHandler&) = delete; 34 | // 不允许赋值 35 | BaseHandler& operator=(const BaseHandler&) = delete; 36 | 37 | // 移动构造函数:允许日志处理器对象之间移动 38 | BaseHandler(BaseHandler&& rhs) noexcept : _formatter(std::move(rhs._formatter)) {}; 39 | 40 | // 析构函数,考虑到会被继承,避免析构时发生资源泄露 41 | virtual ~BaseHandler() {} 42 | 43 | // getForamtter:获取formatter 44 | Formatter getForamtter() const { 45 | return _formatter; 46 | } 47 | 48 | // setForamtter:修改formatter 49 | void setForamtter(Formatter formatter) { 50 | _formatter = formatter; 51 | } 52 | 53 | // format:调用格式化器将record转换成文本字符串 54 | std::string format(const Record& record) { 55 | return _formatter(record); 56 | } 57 | 58 | private: 59 | // 日志处理器的格式化器 60 | Formatter _formatter; 61 | }; 62 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/Level.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace logging { 9 | // 日志等级定义为枚举,枚举值实际类型定义为int8_t,等级越高数值越小 10 | enum class Level : int8_t { 11 | // 严重错误,等级最高 12 | Critical = 0, 13 | // 一般错误 14 | Error = 1, 15 | // 警告信息,一般不会引发程序中断 16 | Warning = 2, 17 | // 普通信息 18 | Info = 3, 19 | // 调试信息,程序调试阶段使用 20 | Debug = 4, 21 | // 程序跟踪信息,程序调试阶段使用,等级最低 22 | Trace = 5, 23 | }; 24 | 25 | // toLevelName:将Level枚举转换成文本 26 | inline const std::string& toLevelName(Level level) 27 | { 28 | // 日志等级与等级文本的映射表 29 | static std::vector LevelNames{ 30 | "CRITICAL", 31 | "ERROR", 32 | "WARN", 33 | "INFO", 34 | "DEBUG", 35 | "TRACE", 36 | }; 37 | 38 | // 使用static_cast将日志等级转换成对应的值 39 | // 然后从映射表中获取对应的等级文本 40 | return LevelNames.at(static_cast(level)); 41 | } 42 | 43 | // operator<<:输出Level 44 | inline std::ostream& operator<<(std::ostream& os, Level level) 45 | { 46 | // 获取Level文本,并输出到输出流中 47 | os << toLevelName(level); 48 | 49 | return os; 50 | } 51 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/Record.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Level.h" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace logging { 9 | // TimePoint表示具体时间点,是标准库time_point具体实现的别名 10 | using TimePoint = std::chrono::time_point; 11 | 12 | // Record类定义 13 | class Record { 14 | public: 15 | // Logger名称 16 | std::string name; 17 | // 日志等级 18 | Level level; 19 | // 日志时间 20 | TimePoint time; 21 | // 日志消息 22 | std::string message; 23 | 24 | // getLevelName:获取日志等级文本 25 | const std::string& getLevelName() const { 26 | // 调用toLevelName获取日志等级文本 27 | return toLevelName(level); 28 | } 29 | }; 30 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/formatters/CFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::cstr { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/formatters/ModernFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::modern { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/formatters/StreamFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::stream { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/handlers/DefaultHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Handler.h" 4 | 5 | namespace logging::handlers { 6 | // 默认日志处理器 7 | template 8 | // 继承BaseHandler 9 | class DefaultHandler : public BaseHandler { 10 | public: 11 | // 构造函数,需要指定格式化器,默认格式化器为defaultFormatter 12 | DefaultHandler(Formatter formatter = defaultFormatter) : BaseHandler(formatter) {} 13 | // 禁止拷贝构造函数 14 | DefaultHandler(const DefaultHandler&) = delete; 15 | // 定义移动构造函数 16 | DefaultHandler(const DefaultHandler&& rhs) noexcept : BaseHandler(rhs.getForamtter()) {} 17 | 18 | // emit用于提交日志记录 19 | // emitLevel > HandlerLevel的日志会被丢弃 20 | template 21 | requires (emitLevel > HandlerLevel) 22 | void emit(const Record& record) { 23 | } 24 | 25 | // emitLevel <= HandlerLevel的日志会被输出到标准输出流中 26 | template 27 | requires (emitLevel <= HandlerLevel) 28 | void emit(const Record& record) { 29 | // 调用format将日志记录对象格式化成文本字符串 30 | std::cout << this->format(record) << std::endl; 31 | } 32 | }; 33 | } -------------------------------------------------------------------------------- /15/Projects/logger/include/logging/handlers/FileHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Handler.h" 4 | #include 5 | #include 6 | 7 | namespace logging::handlers { 8 | template 9 | class FileHandler : public BaseHandler { 10 | public: 11 | FileHandler(const std::string filePath, Formatter formatter = defaultFormatter) : 12 | BaseHandler(formatter), 13 | _stream(filePath.c_str()) { 14 | } 15 | 16 | FileHandler(const std::string filePath, std::ios_base::openmode mode, Formatter formatter = defaultFormatter) : 17 | BaseHandler(formatter), 18 | _stream(filePath.c_str(), mode) { 19 | } 20 | 21 | FileHandler(const FileHandler&) = delete; 22 | FileHandler(FileHandler&& rhs) noexcept : 23 | BaseHandler(rhs.getForamtter()), _stream(std::move(rhs._stream)) {} 24 | 25 | template 26 | requires (emitLevel <= HandlerLevel) 27 | void emit(const Record& record) { 28 | _stream << this->format(record) << std::endl; 29 | } 30 | 31 | template 32 | requires (emitLevel > HandlerLevel) 33 | void emit(const Record& record) { 34 | } 35 | 36 | private: 37 | std::ofstream _stream; 38 | }; 39 | } -------------------------------------------------------------------------------- /15/Projects/logger/src/logging/formatters/CFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "logging/formatters/CFormatter.h" 2 | #include "logging/Record.h" 3 | #include 4 | #include 5 | #include 6 | 7 | namespace logging::formatters::cstr { 8 | // makeTimeString:将time_t结构体转换成字符串 9 | static std::string makeTimeString(time_t timeObj); 10 | 11 | // formatRecord:将Record对象格式化为字符串 12 | std::string formatRecord(const Record& record) { 13 | // LOG_LINE_BUFFER_SIZE表示格式化缓冲区最大长度 14 | static const int32_t LOG_LINE_BUFFER_SIZE = 4096; 15 | 16 | // 将TimePoint类型转换为对应的C标准time_t结构体 17 | time_t timeObj = std::chrono::system_clock::to_time_t(record.time); 18 | // 调用makeTimeString将time_t结构体转换成字符串 19 | std::string timeString = makeTimeString(timeObj); 20 | 21 | // 定义格式化缓冲区,长度为LOG_LINE_BUFFER_SIZE 22 | char logLineBuffer[LOG_LINE_BUFFER_SIZE]; 23 | // 将缓冲区清除为0 24 | memset(logLineBuffer, 0, LOG_LINE_BUFFER_SIZE); 25 | // 调用snprintf格式化,至多输出LOG_LINE_BUFFER_SIZE-1个字符,防止缓冲区溢出 26 | snprintf(logLineBuffer, LOG_LINE_BUFFER_SIZE, "%-16s| [%s] %sZ - %s", 27 | record.name.c_str(), 28 | record.getLevelName().c_str(), 29 | timeString.c_str(), 30 | record.message.c_str() 31 | ); 32 | 33 | // 返回格式化后的字符串 34 | return std::string(logLineBuffer); 35 | } 36 | 37 | static std::string makeTimeString(time_t timeObj) { 38 | // 获取时间缓冲区长度 39 | static constexpr std::size_t TIME_BUFFER_SIZE = std::size("YYYY-mm-ddTHH:MM:SS"); 40 | 41 | // 定义时间字符串格式化缓冲区,长度为TIME_BUFFER_SIZE 42 | char timeBuffer[TIME_BUFFER_SIZE]; 43 | // 将缓冲区清除为0 44 | memset(timeBuffer, 0, TIME_BUFFER_SIZE); 45 | 46 | // 调用strftime完成时间文本格式化,至多输出TIME_BUFFER_SIZE-1个字符,防止缓冲区溢出 47 | std::strftime(std::data(timeBuffer), TIME_BUFFER_SIZE, "%Y-%m-%dT%H:%M:%S", std::localtime(&timeObj)); 48 | 49 | // 返回格式化后的字符串 50 | return std::string(timeBuffer); 51 | } 52 | } -------------------------------------------------------------------------------- /15/Projects/logger/src/logging/formatters/ModernFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "logging/formatters/ModernFormatter.h" 2 | #include "logging/Record.h" 3 | 4 | namespace logging::formatters::modern { 5 | // formatRecord:将Record对象格式化为字符串 6 | std::string formatRecord(const Record& record) { 7 | try { 8 | return std::format( 9 | "{0:<16}| [{1}] {2:%Y-%m-%d}T{2:%H:%M:%OS}Z - {3}", 10 | record.name, 11 | record.getLevelName(), 12 | record.time, 13 | record.message 14 | ); 15 | } 16 | catch (std::exception& e) { 17 | std::cerr << "Error in format: " << e.what() << std::endl; 18 | 19 | return ""; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /15/Projects/logger/src/logging/formatters/StreamFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "logging/formatters/StreamFormatter.h" 2 | #include "logging/Record.h" 3 | #include 4 | #include 5 | 6 | namespace logging::formatters::stream { 7 | // formatRecord:将Record对象格式化为字符串 8 | std::string formatRecord(const Record& record) { 9 | // 获取时间点中的日期(Year-Month-Day) 10 | const std::chrono::year_month_day ymd{ std::chrono::floor(record.time) }; 11 | // 获取时间点中的时间(Hour-Minute-Second) 12 | const std::chrono::hh_mm_ss hms{ record.time - std::chrono::floor(record.time) }; 13 | // 采用输出流生成YYYY-mm-ddTHH:MM:SS.ms格式的文本 14 | std::ostringstream timeStringStream; 15 | timeStringStream << ymd << "T" << hms; 16 | 17 | // 获取时间字符串长度 18 | static constexpr std::size_t TIME_STRING_SIZE = std::size("YYYY-mm-ddTHH:MM:SS"); 19 | // 从输出流中的到的字符串截取我们需要的文本(YYYY-mm-ddTHH:MM:SS),舍弃掉毫秒 20 | std::string timeString = timeStringStream.str().substr(0, TIME_STRING_SIZE - 1) + "Z"; 21 | 22 | // 采用输出流生成格式化日志消息 23 | std::ostringstream logLineStream; 24 | // left左对齐,setw设置固定宽度16 25 | logLineStream << std::left << std::setw(16) << record.name << 26 | "| [" << record.getLevelName() << "] " << 27 | timeString << " - " << 28 | record.message; 29 | 30 | // 返回格式化的文本 31 | return logLineStream.str(); 32 | } 33 | } -------------------------------------------------------------------------------- /16_and_17/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch12) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 9 | add_compile_options(/utf-8) 10 | endif() 11 | 12 | add_executable( 13 | 01-OldBit 14 | Projects/01-OldBit/src/main.cpp 15 | ) 16 | 17 | add_executable( 18 | 02-EndianProcess 19 | Projects/02-EndianProcess/src/main.cpp 20 | ) 21 | 22 | add_executable( 23 | 03-BitCast 24 | Projects/03-BitCast/src/main.cpp 25 | ) 26 | 27 | add_executable( 28 | 04-BitRotating 29 | Projects/04-BitRotating/src/main.cpp 30 | ) 31 | 32 | add_executable( 33 | 05-OtherBit 34 | Projects/05-OtherBit/src/main.cpp 35 | ) 36 | 37 | add_executable( 38 | 06-DataStream 39 | Projects/06-DataStream/src/main.cpp 40 | Projects/06-DataStream/src/data.cpp 41 | Projects/06-DataStream/src/ca/IoUtils.cpp 42 | Projects/06-DataStream/src/ca/TimeUtils.cpp 43 | Projects/06-DataStream/src/ca/algorithms/FunctionalAlgorithm.cpp 44 | Projects/06-DataStream/src/ca/algorithms/ProcedureAlgorithm.cpp 45 | Projects/06-DataStream/src/ca/algorithms/RangesAlgorithm.cpp 46 | Projects/06-DataStream/src/ca/SerializeUtils.cpp 47 | Projects/06-DataStream/include/data.h 48 | Projects/06-DataStream/include/ca/IoUtils.h 49 | Projects/06-DataStream/include/ca/RangeUtils.h 50 | Projects/06-DataStream/include/ca/TimeUtils.h 51 | Projects/06-DataStream/include/ca/Types.h 52 | Projects/06-DataStream/include/ca/BitCompact.h 53 | Projects/06-DataStream/include/ca/BitUtils.h 54 | Projects/06-DataStream/include/ca/SerializeUtils.h 55 | Projects/06-DataStream/include/ca/algorithms/FunctionalAlgorithm.h 56 | Projects/06-DataStream/include/ca/algorithms/ProcedureAlgorithm.h 57 | Projects/06-DataStream/include/ca/algorithms/RangesAlgorithm.h 58 | ) 59 | target_include_directories( 60 | 06-DataStream 61 | PRIVATE 62 | Projects/06-DataStream/include 63 | ) 64 | -------------------------------------------------------------------------------- /16_and_17/CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x64-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ "msvc_x64_x64" ], 8 | "buildRoot": "${projectDir}\\out\\build\\${name}", 9 | "installRoot": "${projectDir}\\out\\install\\${name}", 10 | "cmakeCommandArgs": "", 11 | "buildCommandArgs": "", 12 | "ctestCommandArgs": "" 13 | }, 14 | { 15 | "name": "x64-Release", 16 | "generator": "Ninja", 17 | "configurationType": "RelWithDebInfo", 18 | "buildRoot": "${projectDir}\\out\\build\\${name}", 19 | "installRoot": "${projectDir}\\out\\install\\${name}", 20 | "cmakeCommandArgs": "", 21 | "buildCommandArgs": "", 22 | "ctestCommandArgs": "", 23 | "inheritEnvironments": [ "msvc_x64_x64" ], 24 | "variables": [] 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /16_and_17/Projects/01-OldBit/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | uint32_t value = (0b001101u << 2); 7 | std::cout << std::bitset<8>(value) << std::endl; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /16_and_17/Projects/02-EndianProcess/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | T byteswap(T src) { 8 | T dest = 0; 9 | 10 | for (uint8_t* pSrcByte = reinterpret_cast(&src), 11 | *pDestByte = reinterpret_cast(&dest) + sizeof(T) - 1; 12 | pSrcByte != reinterpret_cast(&src) + sizeof(T); 13 | ++pSrcByte, --pDestByte) { 14 | *pDestByte = *pSrcByte; 15 | } 16 | 17 | return dest; 18 | } 19 | 20 | template 21 | requires (ByteOrder == std::endian::little) 22 | T consumeBigEndian(T src) { 23 | return byteswap(src); 24 | } 25 | 26 | template 27 | requires (ByteOrder == std::endian::big) 28 | T consumeBigEndian(T src) { 29 | return src; 30 | } 31 | 32 | int main() { 33 | uint8_t networkBuffer[] { 34 | 1, 2 35 | }; 36 | 37 | // 将从网络数据流中获取的值直接转换成uint16_t 38 | uint16_t networkValue = *(reinterpret_cast(networkBuffer)); 39 | std::cout << "Original value: " << networkValue << std::endl; 40 | 41 | // 无论如何都转换字节序 42 | uint16_t swappedValue = byteswap(networkValue); 43 | std::cout << "Swaped value: " << swappedValue << std::endl; 44 | 45 | // 仅对字节序为大端的平台转换字节序 46 | uint16_t checkedValue = consumeBigEndian(networkValue); 47 | std::cout << "Checked value: " << checkedValue << std::endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /16_and_17/Projects/03-BitCast/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | float f32v = 784.513f; 7 | uint32_t u32v = std::bit_cast(f32v); 8 | 9 | std::cout << "f32v: " << f32v << std::endl; 10 | std::cout << "u32v: " << u32v << std::endl; 11 | 12 | double f64v = 1123.11f; 13 | uint64_t u64v = std::bit_cast(f64v); 14 | 15 | std::cout << "f64v: " << f64v << std::endl; 16 | std::cout << "u64v: " << u64v << std::endl; 17 | 18 | // 编译错误 19 | //uint16_t u64v = std::bit_cast(f64v); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /16_and_17/Projects/04-BitRotating/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | uint8_t value = 0b01011101; 9 | std::cout << std::setw(16) << std::left << "value" << " = " << std::bitset<8>(value) << std::endl; 10 | std::cout << std::setw(16) << std::left << "rotl" << " = " << std::bitset<8>(std::rotl(value, 2)) << std::endl; 11 | std::cout << std::setw(16) << std::left << "left logical" << " = " << std::bitset<8>(static_cast(value << 2)) << std::endl; 12 | std::cout << std::setw(16) << std::left << "rotr" << " = " << std::bitset<8>(std::rotr(value, 2)) << std::endl; 13 | std::cout << std::setw(16) << std::left << "right logical" << " = " << std::bitset<8>(static_cast(value >> 2)) << std::endl; 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/BitCompact.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if __has_include() 4 | #include 5 | #endif // __has_include() 6 | 7 | #include 8 | #include 9 | 10 | namespace std { 11 | #if !(__cpp_lib_byteswap == 202110L) 12 | // 如果没有std::byteswap,使用自己实现的版本 13 | template 14 | T byteswap(T src) { 15 | T dest = 0; 16 | 17 | for (uint8_t* pSrcByte = reinterpret_cast(&src), 18 | *pDestByte = reinterpret_cast(&dest) + sizeof(T) - 1; 19 | pSrcByte != reinterpret_cast(&src) + sizeof(T); 20 | ++pSrcByte, --pDestByte) { 21 | *pDestByte = *pSrcByte; 22 | } 23 | 24 | return dest; 25 | } 26 | #endif // __cpp_lib_byteswap 27 | 28 | #if !(__cpp_lib_endian == 201907L) 29 | // 如果没有std::endian,使用自己实现的版本 30 | enum class endian { 31 | little, 32 | big, 33 | // 需要根据目标体系结构判断,这里简单设置为little 34 | native = little 35 | }; 36 | #endif // __cpp_lib_endian 37 | 38 | #if !(__cpp_lib_int_pow2 == 202002L) 39 | // 如果没有std::has_single_bit,使用自己实现的版本 40 | template 41 | requires (!std::same_as && !std::same_as && 42 | !std::same_as && !std::same_as && 43 | !std::same_as && !std::same_as) 44 | constexpr bool has_single_bit(T x) noexcept 45 | { 46 | return x != 0 && (x & (x - 1)) == 0; 47 | } 48 | #endif // __cpp_lib_int_pow2 49 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/BitUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/BitCompact.h" 4 | 5 | namespace ca::utils { 6 | // 如果字节序为小端,并且类型size不为1,需要转换字节序 7 | template 8 | requires (ByteOrder == std::endian::little && sizeof(T) != 1) 9 | T consumeBigEndian(T src) { 10 | return std::byteswap(src); 11 | } 12 | 13 | // 如果字节序为小端,但size为1,不需要转换字节序 14 | template 15 | requires (ByteOrder == std::endian::little && sizeof(T) == 1) 16 | T consumeBigEndian(T src) { 17 | return src; 18 | } 19 | 20 | // 如果字节序为大端,但size为1,不需要转换字节序 21 | template 22 | requires (ByteOrder == std::endian::big) 23 | T consumeBigEndian(T src) { 24 | return src; 25 | } 26 | 27 | // 如果字节序为小端,并且类型size不为1,需要转换字节序 28 | template 29 | requires (ByteOrder == std::endian::little && sizeof(T) != 1) 30 | T produceBigEndian(T src) { 31 | return std::byteswap(src); 32 | } 33 | 34 | // 如果字节序为小端,但size为1,不需要转换字节序 35 | template 36 | requires (ByteOrder == std::endian::little && sizeof(T) == 1) 37 | T produceBigEndian(T src) { 38 | return src; 39 | } 40 | 41 | // 如果字节序为大端,但size为1,不需要转换字节序 42 | template 43 | requires (ByteOrder == std::endian::big) 44 | T produceBigEndian(T src) { 45 | return src; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/IoUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | namespace ca::utils { 7 | class Serializer; 8 | class Deserializer; 9 | } 10 | 11 | std::ostream& operator<<( 12 | std::ostream& os, 13 | const ca::types::ChoosedModelObjectTableData& choosedModelObjectTableData 14 | ); 15 | 16 | // 序列化ca::types::ModelView 17 | ca::utils::Serializer& operator<<( 18 | ca::utils::Serializer& serializer, 19 | const ca::types::ModelView& modelView 20 | ); 21 | 22 | // 序列化ca::types::ModelView::Object 23 | ca::utils::Serializer& operator<<( 24 | ca::utils::Serializer& serializer, 25 | const ca::types::ModelView::Object& object 26 | ); 27 | 28 | // 反序列化ca::types::ModelView 29 | ca::utils::Deserializer& operator>>( 30 | ca::utils::Deserializer& deserializer, 31 | ca::types::ModelView& modelView 32 | ); 33 | 34 | // 反序列化ca::types::ModelView::Object 35 | ca::utils::Deserializer& operator>>( 36 | ca::utils::Deserializer& deserializer, 37 | ca::types::ModelView::Object& object 38 | ); 39 | -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/RangeUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace ca::utils { 8 | // 获取range的size(针对无法使用ssize的range) 9 | template 10 | size_t sizeOfRange( 11 | T& range 12 | ) { 13 | return static_cast(std::accumulate( 14 | range.begin(), 15 | range.end(), 16 | 0, 17 | [](int32_t prev, const auto& value) { return prev + 1; } 18 | )); 19 | } 20 | 21 | // 所有的自定义视图和“仿视图”都定义在这里 22 | namespace views { 23 | // |操作符重载所需的一个类型占位符,每个想要放入视图管道的“仿视图”都需要定义一个 24 | template 25 | struct ToFn { 26 | }; 27 | 28 | // Range适配器对象的生成函数,返回ToFn对象 29 | template 30 | ToFn to() { 31 | return ToFn(); 32 | } 33 | 34 | // 操作符|重载。左侧参数是一个视图Range,右侧参数是类型占位符ToFn 35 | template 36 | Container operator | (Range range, const ToFn& fn) { 37 | // 构造容器对象,并调用copy将range中的数据复制到容器中 38 | Container container{}; 39 | std::ranges::copy(range, std::back_inserter(container)); 40 | 41 | return container; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/TimeUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | 5 | namespace ca::utils { 6 | 7 | ca::types::ZonedTime timePointFromString(const std::string& timeString); 8 | 9 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/algorithms/FunctionalAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | #include 6 | 7 | namespace ca::algorithms::functional { 8 | using ModelObjectOutputIterator = std::back_insert_iterator>; 9 | 10 | void parseModelObjectTableData( 11 | // 模型视图begin迭代器 12 | std::vector::const_iterator modelViewsBegin, 13 | // 模型视图end迭代器 14 | std::vector::const_iterator modelViewsEnd, 15 | // 高精度对象集合 16 | const std::set& highResolutionObjectSet, 17 | // 三角面片数上限 18 | int32_t meshCount, 19 | // 低精度对象输出迭代器,用于输出插入低精度对象 20 | ModelObjectOutputIterator lowResolutionObjectOutputIterator, 21 | // 高精度对象输出迭代器,用于输出插入高精度对象 22 | ModelObjectOutputIterator highResolutionObjectOutputIterator 23 | ); 24 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/algorithms/ProcedureAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | namespace ca::algorithms::procedure { 7 | ca::types::ModelObjectTableData parseModelObjectTableData( 8 | // 模型视图数据 9 | std::vector modelViews, 10 | // 高精度对象集合 11 | const std::set& highResolutionObjectSet, 12 | // 三角面片数上限 13 | int32_t meshCount 14 | ); 15 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/ca/algorithms/RangesAlgorithm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | 6 | namespace ca::algorithms::ranges { 7 | ca::types::ModelObjectTableData parseModelObjectTableData( 8 | // 模型视图数据 9 | std::vector modelViews, 10 | // 高精度对象集合 11 | const std::set& highResolutionObjectSet, 12 | // 三角面片数上限 13 | int32_t meshCount 14 | ); 15 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/include/data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ca/Types.h" 4 | #include 5 | #include 6 | #include 7 | 8 | struct ModelObjectsInfo { 9 | // 模型视图数据列表 10 | std::vector modelViews; 11 | // 高精度对象集合 12 | std::set highResolutionObjectSet; 13 | // 3D模型可用三角面片总数 14 | int32_t meshCount; 15 | }; 16 | 17 | ModelObjectsInfo getModelObjectsInfo(); -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/src/ca/SerializeUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ca/SerializeUtils.h" 2 | 3 | ca::utils::Serializer& operator<<(ca::utils::Serializer& ss, const std::string& value) { 4 | return ss 5 | .dumpBE(value.size()) 6 | .dump(value.c_str(), value.size()); 7 | } 8 | 9 | ca::utils::Deserializer& operator>>(ca::utils::Deserializer& ds, std::string& value) { 10 | std::size_t stringSize = 0; 11 | ds.loadBE(stringSize); 12 | 13 | value.resize(stringSize); 14 | ds.load(value.data(), stringSize); 15 | 16 | return ds; 17 | } -------------------------------------------------------------------------------- /16_and_17/Projects/06-DataStream/src/ca/TimeUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ca/TimeUtils.h" 2 | 3 | namespace ca::utils { 4 | 5 | ca::types::ZonedTime timePointFromString(const std::string& timeString) { 6 | namespace chrono = std::chrono; 7 | 8 | constexpr std::string_view TIME_LOCATION = "Asia/Shanghai"; 9 | constexpr std::string_view TIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z"; 10 | 11 | // 根据用户输入的字符串创建一个istringstream对象,作为时间文本解析的输入流 12 | chrono::time_point specifiedTimePoint; 13 | std::istringstream timeStringStream(timeString); 14 | 15 | // 调用chrono的from_stream函数,从字符串流中读取文本,按照TIME_FORMAT格式进行解析,解析后的时间存储在specifiedTimePoint中。 16 | chrono::from_stream( 17 | timeStringStream, 18 | TIME_FORMAT.data(), 19 | specifiedTimePoint 20 | ); 21 | 22 | // 按照时间字符串中的时区和解析得到的time_point构造zoned_time对象 23 | std::chrono::zoned_time zonedSpecifiedTimePoint { 24 | TIME_LOCATION, 25 | specifiedTimePoint 26 | }; 27 | 28 | return zonedSpecifiedTimePoint; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /18/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(ch18) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 9 | add_compile_options(/utf-8) 10 | endif() 11 | 12 | add_executable( 13 | 01-JThreadSample 14 | Projects/01-JThreadSample/src/main.cpp 15 | ) 16 | 17 | add_executable( 18 | 02-SourceLocation 19 | Projects/02-SourceLocation/src/main.cpp 20 | ) 21 | 22 | add_executable( 23 | 03-Calendar 24 | Projects/03-Calendar/src/main.cpp 25 | ) 26 | 27 | add_executable( 28 | 04-Timezone 29 | Projects/04-Timezone/src/main.cpp 30 | ) 31 | 32 | add_executable( 33 | 05-SyncStream 34 | Projects/05-SyncStream/src/main.cpp 35 | ) 36 | 37 | add_executable( 38 | 06-U8String 39 | Projects/06-U8String/src/main.cpp 40 | ) 41 | 42 | add_executable( 43 | 07-WindowsThread 44 | Projects/07-WindowsThread/src/main.cpp 45 | ) 46 | -------------------------------------------------------------------------------- /18/Projects/01-OldBit/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | std::setlocale(LC_ALL, "en_US.utf8"); 10 | 11 | std::u8string utf8String = u8"你好,这是UTF-8"; 12 | std::cout << "Processing " << utf8String.size() << " bytes: [ " << std::showbase; 13 | for (char8_t c : utf8String) { 14 | std::cout << std::hex << +c << ' '; 15 | } 16 | std::cout << "]\n"; 17 | 18 | const char* utf8Current = reinterpret_cast(&utf8String[0]); 19 | const char* utf8End = reinterpret_cast(&utf8String[0] + utf8String.size()); 20 | char16_t c16; 21 | std::mbstate_t convertState{}; 22 | 23 | std::u16string utf16String; 24 | while (std::size_t rc = std::mbrtoc16(&c16, utf8Current, utf8End - utf8Current + 1, &convertState)) { 25 | std::cout << "Next UTF-16 char: " << std::hex 26 | << static_cast(c16) << " obtained from "; 27 | 28 | if (rc == (std::size_t)-3) 29 | std::cout << "earlier surrogate pair\n"; 30 | else if (rc == (std::size_t)-2) 31 | break; 32 | else if (rc == (std::size_t)-1) 33 | break; 34 | else { 35 | std::cout << std::dec << rc << " bytes [ "; 36 | for (std::size_t n = 0; n < rc; ++n) 37 | std::cout << std::hex << +static_cast(utf8Current[n]) << ' '; 38 | std::cout << "]\n"; 39 | utf8Current += rc; 40 | utf16String.push_back(c16); 41 | } 42 | } 43 | 44 | std::ofstream u8OutputFile("out.utf8.txt", std::ios::binary); 45 | u8OutputFile.write(reinterpret_cast(utf8String.data()), utf8String.size() * sizeof(char8_t)); 46 | 47 | std::cout << std::dec << utf16String.size() << std::endl; 48 | std::ofstream u16OutputFile("out.utf16.txt", std::ios::binary); 49 | u16OutputFile.write(reinterpret_cast(utf16String.data()), utf16String.size() * sizeof(char16_t)); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /18/Projects/02-SourceLocation/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void logInnerLocation(const std::string& message); 6 | void logLocation( 7 | const std::string& message, 8 | std::source_location location = std::source_location::current() 9 | ); 10 | 11 | int main() { 12 | logInnerLocation("Inner location message"); 13 | // 通过默认参数通过current获取source_location对象 14 | // 这时source_location包含的信息就是在main内 15 | logLocation("Location message"); 16 | 17 | return 0; 18 | } 19 | 20 | void logInnerLocation(const std::string& message) { 21 | // 在logInnerLocation内部通过current获取source_location对象 22 | // 这时source_location包含的信息就是在logInnerLocation内 23 | std::source_location location = std::source_location::current(); 24 | 25 | std::cerr << message << std::endl << 26 | " [" << 27 | location.file_name() << "(" << 28 | location.line() << ":" << 29 | location.column() << ")@" << 30 | location.function_name() << "]" << std::endl; 31 | } 32 | 33 | void logLocation( 34 | const std::string& message, 35 | std::source_location location 36 | ) { 37 | std::cerr << message << std::endl << 38 | " [" << 39 | location.file_name() << "(" << 40 | location.line() << ":" << 41 | location.column() << ")@" << 42 | location.function_name() << "]" << std::endl; 43 | } 44 | -------------------------------------------------------------------------------- /18/Projects/05-SyncStream/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace chrono = std::chrono; 9 | 10 | // 普通stream版本 11 | void coutPrinter(const std::string message1, const std::string message2); 12 | // syncstream版本 13 | void syncStreamPrinter(const std::string message1, const std::string message2); 14 | 15 | int main() { 16 | std::cout << "Cout workers:" << std::endl; 17 | // 创建多个thread 18 | std::vector coutWorkers; 19 | for (int32_t workerIndex = 0; workerIndex < 10; ++workerIndex) { 20 | std::thread coutWorker(coutPrinter, 21 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 22 | "abcdefghijklmnopqrstuvwxyz" 23 | ); 24 | coutWorkers.push_back(std::move(coutWorker)); 25 | } 26 | 27 | // 普通thread需要手动join 28 | for (auto& worker : coutWorkers) { 29 | if (worker.joinable()) { 30 | worker.join(); 31 | } 32 | } 33 | 34 | std::cout << "SyncStream workers:" << std::endl; 35 | // 创建多个jthread,会在析构时自动join 36 | std::vector syncStreamWorkers; 37 | for (int32_t workerIndex = 0; workerIndex < 10; ++workerIndex) { 38 | std::jthread syncStreamWorker( 39 | syncStreamPrinter, 40 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 41 | "abcdefghijklmnopqrstuvwxyz" 42 | ); 43 | syncStreamWorkers.push_back(std::move(syncStreamWorker)); 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | void coutPrinter(const std::string message1, const std::string message2) { 50 | std::cout << message1 << " " << message2 << std::endl; 51 | } 52 | 53 | void syncStreamPrinter(const std::string message1, const std::string message2) { 54 | // 使用std::osyncstream包装输出流对象即可 55 | std::osyncstream(std::cout) << message1 << " " << message2 << std::endl; 56 | } 57 | -------------------------------------------------------------------------------- /18/Projects/07-WindowsThread/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void simpleSleep() { 9 | using namespace std::literals::chrono_literals; 10 | 11 | std::cout << "[SIMPLE] Before simple sleep" << std::endl; 12 | std::this_thread::sleep_for(2000ms); 13 | std::cout << "[SIMPLE] After simple sleep" << std::endl; 14 | } 15 | 16 | int main() { 17 | std::cout << "[MAIN] Before create simple thread" << std::endl; 18 | std::thread simpleWorker(simpleSleep); 19 | // 获取native handle 20 | auto nativeWorkerHandle = simpleWorker.native_handle(); 21 | // 设置线程优先级 22 | std::cout << "THREAD_PRIORITY_HIGHEST: " << THREAD_PRIORITY_HIGHEST << std::endl; 23 | ::SetThreadPriority(nativeWorkerHandle, THREAD_PRIORITY_HIGHEST); 24 | std::cout << "Thread Priority: " << ::GetThreadPriority(nativeWorkerHandle) << std::endl; 25 | 26 | simpleWorker.join(); 27 | 28 | std::cout << "[MAIN] Main function exited" << std::endl; 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /19/Projects/calendar/include/Logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Logger.h" 4 | #include "logging/formatters/CFormatter.h" 5 | #include "logging/handlers/StreamHandler.h" 6 | #include "logging/handlers/FileHandler.h" 7 | 8 | using LoggerType = decltype(logging::LoggerFactory::createLogger("Calendar++", std::make_tuple( 9 | logging::handlers::StreamHandler(logging::formatters::cstr::formatRecord), 10 | logging::handlers::FileHandler("logs/calendarpp.log", logging::formatters::cstr::formatRecord) 11 | ))); 12 | 13 | LoggerType& getLogger(); 14 | -------------------------------------------------------------------------------- /19/Projects/calendar/include/actions/ExitAction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace calendarpp::actions { 4 | void exitApp(); 5 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/actions/ExportAction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace calendarpp::actions { 4 | void exportCurrentYear(); 5 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/actions/ShowAction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace calendarpp::actions { 4 | void showCurrentMonth(); 5 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/menu/Menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace calendarpp::menu { 6 | using Action = std::function; 7 | 8 | void showMenu(); 9 | void readAction(); 10 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/utils/CalendarUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace calendarpp::utils { 7 | std::vector> buildMonthWeeks(std::chrono::year_month yearMonth); 8 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/utils/IOUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace calendarpp::utils { 6 | void writeFile(const std::string& filePath, const std::string& fileContent); 7 | } -------------------------------------------------------------------------------- /19/Projects/calendar/include/utils/RenderUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace calendarpp::utils { 7 | std::string renderNow(); 8 | std::string renderMonth(std::chrono::year_month yearMonth); 9 | std::string renderYear(std::chrono::year year); 10 | } -------------------------------------------------------------------------------- /19/Projects/calendar/src/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.h" 2 | 3 | LoggerType& getLogger() { 4 | using logging::LoggerFactory; 5 | using logging::Level; 6 | using logging::handlers::StreamHandler; 7 | using logging::handlers::FileHandler; 8 | using logging::formatters::cstr::formatRecord; 9 | 10 | static auto logger = LoggerFactory::createLogger("Calendar++", std::make_tuple( 11 | StreamHandler(formatRecord), 12 | FileHandler::create("logs/calendarpp.log", formatRecord) 13 | )); 14 | 15 | return logger; 16 | } 17 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/actions/ExitAction.cpp: -------------------------------------------------------------------------------- 1 | #include "actions/ExitAction.h" 2 | #include 3 | #include 4 | 5 | namespace calendarpp::actions { 6 | void exitApp() { 7 | std::cout << "程序退出中 ..." << std::endl; 8 | 9 | exit(0); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/actions/ExportAction.cpp: -------------------------------------------------------------------------------- 1 | #include "actions/ExportAction.h" 2 | #include "utils/RenderUtils.h" 3 | #include "utils/IOUtils.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace chrono = std::chrono; 10 | 11 | namespace calendarpp::actions { 12 | void exportCurrentYear() { 13 | // 获取当前时间 14 | chrono::time_point now{ chrono::system_clock::now() }; 15 | // 将时间转换为year_month_day 16 | chrono::year_month_day ymd{ chrono::floor(now) }; 17 | // 获取当前年份 18 | chrono::year currentYear = ymd.year(); 19 | 20 | // 提示并读取用户输入 21 | std::cout << "请输入导出文件路径: "; 22 | std::string filePath; 23 | std::getline(std::cin, filePath); 24 | 25 | // 调用IO模块将renderYear的渲染结果输出到文件中 26 | utils::writeFile(filePath, utils::renderYear(currentYear)); 27 | 28 | std::cout << std::format("已将日历导出到文件中: {}", filePath) << std::endl; 29 | std::cout << std::endl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/actions/ShowAction.cpp: -------------------------------------------------------------------------------- 1 | #include "actions/ShowAction.h" 2 | #include "utils/RenderUtils.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace chrono = std::chrono; 9 | 10 | namespace calendarpp::actions { 11 | void showCurrentMonth() { 12 | // 获取当前时间 13 | chrono::time_point now{ chrono::system_clock::now() }; 14 | // 将时间转换为year_month_day 15 | chrono::year_month_day ymd{ chrono::floor(now) }; 16 | // 获取当前年月(类型为year_month) 17 | chrono::year_month currentYearMonth = ymd.year() / ymd.month(); 18 | 19 | // 调用渲染模块渲染当月日历 20 | std::cout << std::endl; 21 | std::cout << utils::renderMonth(currentYearMonth); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "menu/Menu.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | using namespace std::literals::chrono_literals; 8 | 9 | auto now = std::chrono::utc_clock::now(); 10 | std::cout << now << std::endl; 11 | 12 | auto prev = now - 13h; 13 | std::cout << prev << std::endl; 14 | 15 | auto sys_now = std::chrono::utc_clock::to_sys(prev); 16 | std::cout << sys_now << std::endl; 17 | 18 | const std::chrono::year_month_day ymd{ std::chrono::floor( 19 | std::chrono::utc_clock::to_sys(prev) 20 | )}; 21 | std::cout << ymd << std::endl; 22 | 23 | while (true) { 24 | // 展示菜单 25 | calendarpp::menu::showMenu(); 26 | // 读取并执行菜单项 27 | calendarpp::menu::readAction(); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/utils/CalendarUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils/CalendarUtils.h" 2 | #include 3 | 4 | namespace chrono = std::chrono; 5 | using namespace std::literals::chrono_literals; 6 | 7 | static uint32_t MaxWeekdayIndex = 6; 8 | 9 | namespace calendarpp::utils { 10 | std::vector> buildMonthWeeks(std::chrono::year_month yearMonth) { 11 | // 获取当月第一天 12 | const auto firstDay = yearMonth / 1d; 13 | // 获取当月最后一天 14 | const auto lastDay = chrono::year_month_day(yearMonth / chrono::last); 15 | 16 | std::vector> monthWeeks; 17 | 18 | // 将当月第一天设定为当日 19 | auto currentDay = firstDay; 20 | // 当每周当日超出当月最后一天时中止循环 21 | while (currentDay <= lastDay) { 22 | // 每次循环都计算出当日所在周的7天(周一到周日) 23 | std::vector currentMonthWeek; 24 | 25 | // 通过weekday获取某一天是周几 26 | auto currentWeekday = chrono::weekday{ std::chrono::sys_days{ currentDay } }; 27 | // 通过iso_encoding获取周几的编码(1-7) 28 | auto currentWeekdayIndex = currentWeekday.iso_encoding() - 1; 29 | 30 | // 计算本周第一天 31 | auto firstDayOfWeek = chrono::year_month_day{ 32 | std::chrono::sys_days{ currentDay } - chrono::days(currentWeekdayIndex) 33 | }; 34 | 35 | currentDay = firstDayOfWeek; 36 | // 计算出本周的所有日期并添加到currentMonthWeek中 37 | for (uint32_t weekdayIndex = 0; weekdayIndex <= MaxWeekdayIndex; ++weekdayIndex) { 38 | currentMonthWeek.push_back(currentDay); 39 | 40 | currentDay = chrono::year_month_day{ 41 | std::chrono::sys_days{ currentDay } + chrono::days(1) 42 | }; 43 | } 44 | // 将计算好的当前周添加到monthWeeks中 45 | monthWeeks.push_back(currentMonthWeek); 46 | } 47 | 48 | return monthWeeks; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /19/Projects/calendar/src/utils/IOUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils/IOUtils.h" 2 | #include "Logger.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace fs = std::filesystem; 9 | 10 | namespace calendarpp::utils { 11 | void writeFile(const std::string& filePath, const std::string& fileContent) { 12 | auto& logger = getLogger(); 13 | 14 | // 检测文件是否存在 15 | if (fs::exists(filePath)) { 16 | logger.warning(std::format("Override existed file: {}", filePath)); 17 | } 18 | 19 | // 由于源代码使用UTF-8,生成的字符串就是UTF-8,因此可以直接强制类型转换构建u8string 20 | std::u8string utf8FileContent(reinterpret_cast(fileContent.c_str()), fileContent.size()); 21 | 22 | // 将u8string以二进制形式写入到文件中 23 | std::ofstream outputFile(filePath, std::ios::binary); 24 | outputFile.write(reinterpret_cast(utf8FileContent.data()), utf8FileContent.size()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/Formatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Record.h" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace logging { 9 | // Formatter类型,所有将日志记录转换成字符串的函数/仿函数和Lambda都可以作为Formatter 10 | using Formatter = std::function; 11 | 12 | // defaultFormatter:默认格式化器 13 | inline std::string defaultFormatter(const Record& record) { 14 | // 调用format返回简单的日志信息 15 | return std::format("{}:{}:{}", record.getLevelName(), record.name, record.message); 16 | } 17 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/Level.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace logging { 9 | // 日志等级定义为枚举,枚举值实际类型定义为int8_t,等级越高数值越小 10 | enum class Level : int8_t { 11 | // 严重错误,等级最高 12 | Critical = 0, 13 | // 一般错误 14 | Error = 1, 15 | // 警告信息,一般不会引发程序中断 16 | Warning = 2, 17 | // 普通信息 18 | Info = 3, 19 | // 调试信息,程序调试阶段使用 20 | Debug = 4, 21 | // 程序跟踪信息,程序调试阶段使用,等级最低 22 | Trace = 5, 23 | }; 24 | 25 | // toLevelName:将Level枚举转换成文本 26 | inline const std::string& toLevelName(Level level) 27 | { 28 | // 日志等级与等级文本的映射表 29 | static std::vector LevelNames{ 30 | "CRITICAL", 31 | "ERROR", 32 | "WARN", 33 | "INFO", 34 | "DEBUG", 35 | "TRACE", 36 | }; 37 | 38 | // 使用static_cast将日志等级转换成对应的值 39 | // 然后从映射表中获取对应的等级文本 40 | return LevelNames.at(static_cast(level)); 41 | } 42 | 43 | // operator<<:输出Level 44 | inline std::ostream& operator<<(std::ostream& os, Level level) 45 | { 46 | // 获取Level文本,并输出到输出流中 47 | os << toLevelName(level); 48 | 49 | return os; 50 | } 51 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/Record.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Level.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace logging { 10 | // TimePoint表示具体时间点,是标准库time_point具体实现的别名 11 | using TimePoint = std::chrono::time_point; 12 | 13 | // Record类定义 14 | class Record { 15 | public: 16 | // Logger名称 17 | std::string name; 18 | // 日志等级 19 | Level level; 20 | // 日志时间 21 | TimePoint time; 22 | // 日志消息 23 | std::string message; 24 | std::source_location sourceLocation; 25 | 26 | // getLevelName:获取日志等级文本 27 | const std::string& getLevelName() const { 28 | // 调用toLevelName获取日志等级文本 29 | return toLevelName(level); 30 | } 31 | }; 32 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/formatters/CFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::cstr { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/formatters/ModernFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::modern { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/formatters/StreamFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace logging { 6 | class Record; 7 | 8 | namespace formatters::stream { 9 | // formatRecord函数用于格式化日志记录对象 10 | std::string formatRecord(const logging::Record& record); 11 | } 12 | } -------------------------------------------------------------------------------- /19/Projects/logger/include/logging/handlers/DefaultHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "logging/Handler.h" 4 | #include 5 | 6 | namespace logging::handlers { 7 | // 默认日志处理器 8 | template 9 | // 继承BaseHandler 10 | class DefaultHandler : public BaseHandler { 11 | public: 12 | // 构造函数,需要指定格式化器,默认格式化器为defaultFormatter 13 | DefaultHandler(Formatter formatter = defaultFormatter) : BaseHandler(formatter) {} 14 | // 禁止拷贝构造函数 15 | DefaultHandler(const DefaultHandler&) = delete; 16 | // 定义移动构造函数 17 | DefaultHandler(const DefaultHandler&& rhs) noexcept : BaseHandler(rhs.getForamtter()) {} 18 | 19 | // emit用于提交日志记录 20 | // emitLevel > HandlerLevel的日志会被丢弃 21 | template 22 | requires (emitLevel > HandlerLevel) 23 | void emit(const Record& record) { 24 | } 25 | 26 | // emitLevel <= HandlerLevel的日志会被输出到标准输出流中 27 | template 28 | requires (emitLevel <= HandlerLevel) 29 | void emit(const Record& record) { 30 | // 调用format将日志记录对象格式化成文本字符串 31 | std::osyncstream(std::cout) << this->format(record) << std::endl; 32 | } 33 | }; 34 | } -------------------------------------------------------------------------------- /19/Projects/logger/src/logging/formatters/ModernFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "logging/formatters/ModernFormatter.h" 2 | #include "logging/Record.h" 3 | 4 | namespace logging::formatters::modern { 5 | // formatRecord:将Record对象格式化为字符串 6 | std::string formatRecord(const Record& record) { 7 | const auto& sourceLocation = record.sourceLocation; 8 | 9 | try { 10 | return std::format( 11 | "{0:<16}| [{1}] {2:%Y-%m-%d}T{2:%H:%M:%OS}Z - <{3}:{4} [{5}]> - {6}", 12 | record.name, 13 | record.getLevelName(), 14 | record.time, 15 | sourceLocation.file_name(), 16 | sourceLocation.line(), 17 | sourceLocation.function_name(), 18 | record.message 19 | ); 20 | } 21 | catch (std::exception& e) { 22 | std::cerr << "Error in format: " << e.what() << std::endl; 23 | 24 | return ""; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /19/Projects/logger/src/logging/formatters/StreamFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "logging/formatters/StreamFormatter.h" 2 | #include "logging/Record.h" 3 | #include 4 | #include 5 | 6 | namespace logging::formatters::stream { 7 | // formatRecord:将Record对象格式化为字符串 8 | std::string formatRecord(const Record& record) { 9 | // 获取时间点中的日期(Year-Month-Day) 10 | const std::chrono::year_month_day ymd{ std::chrono::floor(record.time) }; 11 | // 获取时间点中的时间(Hour-Minute-Second) 12 | const std::chrono::hh_mm_ss hms{ record.time - std::chrono::floor(record.time) }; 13 | // 采用输出流生成YYYY-mm-ddTHH:MM:SS.ms格式的文本 14 | std::ostringstream timeStringStream; 15 | timeStringStream << ymd << "T" << hms; 16 | 17 | // 获取时间字符串长度 18 | static constexpr std::size_t TIME_STRING_SIZE = std::size("YYYY-mm-ddTHH:MM:SS"); 19 | // 从输出流中的到的字符串截取我们需要的文本(YYYY-mm-ddTHH:MM:SS),舍弃掉毫秒 20 | std::string timeString = timeStringStream.str().substr(0, TIME_STRING_SIZE - 1) + "Z"; 21 | 22 | // 采用输出流生成格式化日志消息 23 | std::ostringstream logLineStream; 24 | const auto& sourceLocation = record.sourceLocation; 25 | // left左对齐,setw设置固定宽度16 26 | logLineStream << std::left << std::setw(16) << record.name << 27 | "| [" << record.getLevelName() << "] " << 28 | timeString << " - <" << 29 | sourceLocation.file_name() << ":" << 30 | sourceLocation.line() << " [" << 31 | sourceLocation.function_name() << 32 | "]> - " << 33 | record.message; 34 | 35 | // 返回格式化的文本 36 | return logLineStream.str(); 37 | } 38 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![course-logo](https://github.com/samblg/cpp20-plus-indepth/raw/main/cpp20-plus-and-evermore.png) 2 | 3 | -------------------------------------------------------------------------------- 4 | 5 | # Learn C++20 In Depth and Evermore 6 | 7 | This is the repository of the source code for course ___Learn C++20 In Depth and Evermore___. 8 | 9 | Pull requests of cmake/make are welcome! 10 | 11 | 12 | ## Requirements 13 | 14 | * Basic development environment : 15 | * Windows 10 or higher with Visual C++ (through Visual Studio 2022 17.4.1 or higher) 16 | * Linux with GCC 12.2.0 (may work, not fully tested) 17 | * macOS 12 or higher with Clang 15.0.2-1 (may work, not fully tested) 18 | 19 | 20 | ## References 21 | 22 | * [ISO C++](http://www.open-std.org/jtc1/sc22/wg21/) 23 | * [cppreference](https://en.cppreference.com/w/) 24 | 25 | 26 | ## Useful Links 27 | 28 | * [Visual Studio](https://visualstudio.microsoft.com/vs/community) 29 | * [GCC](http://gcc.gnu.org/) 30 | * [Clang](http://clang.llvm.org/) 31 | 32 | -------------------------------------------------------------------------------- /cpp20-plus-and-evermore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/samblg/cpp20-plus-indepth/78b6f53d6ec83ef2e029d78777c7834cb7ab99eb/cpp20-plus-and-evermore.png -------------------------------------------------------------------------------- /mid_term_exam_sol/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "iosfwd": "cpp", 4 | "vector": "cpp", 5 | "*.ixx": "cpp" 6 | } 7 | } -------------------------------------------------------------------------------- /mid_term_exam_sol/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | set (TARGET AsyncCpp) 4 | 5 | project(${TARGET}) 6 | 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | set(CXX_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 10 | 11 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 12 | add_custom_target(std_modules ALL 13 | COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules" 14 | COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream cstdint type_traits string filesystem functional coroutine thread chrono mutex vector 15 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 16 | ) 17 | endif() 18 | 19 | function (prepare_for_module TGT) 20 | target_compile_options(${TGT} PUBLIC -fmodules-ts) 21 | set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20) 22 | set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF) 23 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 24 | add_dependencies(${TGT} std_modules) 25 | endif() 26 | endfunction() 27 | 28 | set (MODULE_EXT cpp) 29 | if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 30 | set (MODULE_EXT ixx) 31 | add_compile_options(/utf-8) 32 | endif() 33 | 34 | add_executable( 35 | ${TARGET} 36 | src/core/Concepts.${MODULE_EXT} 37 | src/core/Core.${MODULE_EXT} 38 | src/task/AsyncTaskQueue.${MODULE_EXT} 39 | src/hp/AsyncHpTask.${MODULE_EXT} 40 | src/hp/AsyncHpLoop.${MODULE_EXT} 41 | src/hp/Hp.${MODULE_EXT} 42 | src/task/Coroutine.${MODULE_EXT} 43 | src/task/AsyncTaskLoop.${MODULE_EXT} 44 | src/task/Asyncify.${MODULE_EXT} 45 | src/task/Task.${MODULE_EXT} 46 | src/io/AsyncIoTask.${MODULE_EXT} 47 | src/io/AsyncIoLoop.${MODULE_EXT} 48 | src/io/AsyncIoAsyncify.${MODULE_EXT} 49 | src/io/Io.${MODULE_EXT} 50 | src/fs/FileSystem.${MODULE_EXT} 51 | src/main.cpp 52 | ) 53 | 54 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 55 | prepare_for_module(${TARGET}) 56 | endif() 57 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/core/Concepts.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.core:concepts; 2 | 3 | import ; 4 | 5 | namespace asyncpp::core { 6 | export template 7 | concept Invocable = std::is_invocable_v; 8 | } -------------------------------------------------------------------------------- /mid_term_exam_sol/src/core/Concepts.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.core:concepts; 2 | 3 | import ; 4 | 5 | namespace asyncpp::core { 6 | export template 7 | concept Invocable = std::is_invocable_v; 8 | } 9 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/core/Core.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.core; 2 | 3 | export import :concepts; -------------------------------------------------------------------------------- /mid_term_exam_sol/src/core/Core.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.core; 2 | 3 | export import :concepts; 4 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/fs/FileSystem.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.fs; 2 | 3 | import asyncpp.io; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::fs { 10 | using asyncpp::io::ioAsyncify; 11 | namespace fs = std::filesystem; 12 | 13 | export auto createDirectories(const std::string& directoryPath) { 14 | return ioAsyncify([directoryPath]() { 15 | return fs::create_directories(directoryPath); 16 | }); 17 | } 18 | 19 | export auto exists(const std::string& directoryPath) { 20 | return ioAsyncify([directoryPath]() { 21 | return fs::exists(directoryPath); 22 | }); 23 | } 24 | 25 | export auto removeAll(const std::string& directoryPath) { 26 | return ioAsyncify([directoryPath]() { 27 | return fs::remove_all(directoryPath); 28 | }); 29 | } 30 | 31 | export auto voidFsFunction(const std::string& directoryPath) { 32 | return ioAsyncify([directoryPath]() { 33 | std::cout << directoryPath << std::endl; 34 | }); 35 | } 36 | } -------------------------------------------------------------------------------- /mid_term_exam_sol/src/fs/FileSystem.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.fs; 2 | 3 | import asyncpp.io; 4 | import ; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::fs { 10 | using asyncpp::io::ioAsyncify; 11 | namespace fs = std::filesystem; 12 | 13 | export auto createDirectories(const std::string& directoryPath) { 14 | return ioAsyncify([directoryPath]() { 15 | return fs::create_directories(directoryPath); 16 | }); 17 | } 18 | 19 | export auto exists(const std::string& directoryPath) { 20 | return ioAsyncify([directoryPath]() { 21 | return fs::exists(directoryPath); 22 | }); 23 | } 24 | 25 | export auto removeAll(const std::string& directoryPath) { 26 | return ioAsyncify([directoryPath]() { 27 | return fs::remove_all(directoryPath); 28 | }); 29 | } 30 | 31 | export auto voidFsFunction(const std::string& directoryPath) { 32 | return ioAsyncify([directoryPath]() { 33 | std::cout << directoryPath << std::endl; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/hp/AsyncHpLoop.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | 3 | #ifndef _WINDOWS_ 4 | #include 5 | #endif // _WINDOWS_ 6 | 7 | export module asyncpp.hp:loop; 8 | 9 | import :task; 10 | import asyncpp.task.queue; 11 | 12 | import ; 13 | import ; 14 | import ; 15 | import ; 16 | 17 | namespace asyncpp::hp { 18 | export class AsyncHpLoop { 19 | public: 20 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 21 | static const int32_t SLEEP_MS = 100; 22 | 23 | static AsyncHpLoop& start(); 24 | 25 | private: 26 | // 支持单例模式,将其定义为private,防止外部调用构造函数 27 | AsyncHpLoop() { 28 | _thread = std::jthread(std::bind(&AsyncHpLoop::loopMain, this)); 29 | auto nativeWorkerHandle = _thread.native_handle(); 30 | ::SetThreadPriority(nativeWorkerHandle, THREAD_PRIORITY_HIGHEST); 31 | } 32 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 33 | AsyncHpLoop(const AsyncHpLoop&) = delete; 34 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 35 | AsyncHpLoop& operator=(const AsyncHpLoop&) = delete; 36 | 37 | void loopExecution() { 38 | AsyncHpTask opItem; 39 | if (!AsyncHpTaskQueue::getInstance().dequeue(&opItem)) { 40 | return; 41 | } 42 | 43 | opItem.taskHandler(); 44 | 45 | auto& asyncEventQueue = asyncpp::task::AsyncTaskQueue::getInstance(); 46 | asyncEventQueue.enqueue({ 47 | .handler = opItem.resumeHandler 48 | }); 49 | } 50 | 51 | void loopMain() { 52 | while (true) { 53 | loopExecution(); 54 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 55 | } 56 | } 57 | 58 | // jthread对象,为高性能计算线程,jthread让该线程结束之前整个进程都不会结束 59 | std::jthread _thread; 60 | }; 61 | 62 | AsyncHpLoop& AsyncHpLoop::start() { 63 | static AsyncHpLoop ioLoop; 64 | 65 | return ioLoop; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/hp/AsyncHpTask.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.hp:task; 2 | 3 | import asyncpp.core; 4 | import ; 5 | import ; 6 | import ; 7 | 8 | namespace asyncpp::hp { 9 | 10 | export struct AsyncHpTask { 11 | using ResumeHandler = std::function; 12 | using TaskHandler = std::function; 13 | 14 | // 协程唤醒函数 15 | ResumeHandler resumeHandler; 16 | // 计算任务函数 17 | TaskHandler taskHandler; 18 | }; 19 | 20 | export class AsyncHpTaskQueue { 21 | public: 22 | static AsyncHpTaskQueue& getInstance(); 23 | 24 | void enqueue(const AsyncHpTask& item) { 25 | std::lock_guard guard(_queueMutex); 26 | 27 | _queue.push_back(item); 28 | } 29 | 30 | bool dequeue(AsyncHpTask* item) { 31 | std::lock_guard guard(_queueMutex); 32 | 33 | if (_queue.size() == 0) { 34 | return false; 35 | } 36 | 37 | *item = _queue.back(); 38 | _queue.pop_back(); 39 | 40 | return true; 41 | } 42 | 43 | size_t getSize() const { 44 | return _queue.size(); 45 | } 46 | 47 | private: 48 | // 高性能计算任务队列 49 | std::vector _queue; 50 | // 高性能计算任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 51 | std::mutex _queueMutex; 52 | }; 53 | 54 | AsyncHpTaskQueue& AsyncHpTaskQueue::getInstance() { 55 | static AsyncHpTaskQueue queue; 56 | 57 | return queue; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/hp/Hp.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.hp; 2 | 3 | export import :loop; 4 | export import :task; 5 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/AsyncIoLoop.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:loop; 2 | 3 | import :task; 4 | import asyncpp.task; 5 | 6 | import ; 7 | import ; 8 | import ; 9 | 10 | namespace asyncpp::io { 11 | export class AsyncIoLoop { 12 | public: 13 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 14 | static const int32_t SLEEP_MS = 1000; 15 | 16 | static AsyncIoLoop& start(); 17 | 18 | private: 19 | // 支持单例模式,将其定义未private,防止外部调用构造函数 20 | AsyncIoLoop() { 21 | _thread = std::jthread(std::bind(&AsyncIoLoop::loopMain, this)); 22 | } 23 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 24 | AsyncIoLoop(const AsyncIoLoop&) = delete; 25 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 26 | AsyncIoLoop& operator=(const AsyncIoLoop&) = delete; 27 | 28 | void loopExecution() { 29 | AsyncIoTask opItem; 30 | if (!AsyncIoTaskQueue::getInstance().dequeue(&opItem)) { 31 | return; 32 | } 33 | 34 | opItem.taskHandler(); 35 | 36 | auto& asyncEventQueue = asyncpp::task::AsyncTaskQueue::getInstance(); 37 | asyncEventQueue.enqueue({ 38 | .handler = opItem.resumeHandler 39 | }); 40 | } 41 | 42 | void loopMain() { 43 | while (true) { 44 | loopExecution(); 45 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 46 | } 47 | } 48 | 49 | // jthread对象,为I/O线程,jthread让该线程结束之前整个进程都不会结束 50 | std::jthread _thread; 51 | }; 52 | 53 | AsyncIoLoop& AsyncIoLoop::start() { 54 | static AsyncIoLoop ioLoop; 55 | 56 | return ioLoop; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/AsyncIoLoop.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:loop; 2 | 3 | import :task; 4 | import asyncpp.task; 5 | 6 | import ; 7 | import ; 8 | import ; 9 | import ; 10 | 11 | namespace asyncpp::io { 12 | export class AsyncIoLoop { 13 | public: 14 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 15 | static const int32_t SLEEP_MS = 1000; 16 | 17 | static AsyncIoLoop& start(); 18 | 19 | private: 20 | // 支持单例模式,将其定义未private,防止外部调用构造函数 21 | AsyncIoLoop() { 22 | _thread = std::jthread(std::bind(&AsyncIoLoop::loopMain, this)); 23 | } 24 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 25 | AsyncIoLoop(const AsyncIoLoop&) = delete; 26 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 27 | AsyncIoLoop& operator=(const AsyncIoLoop&) = delete; 28 | 29 | void loopExecution() { 30 | AsyncIoTask opItem; 31 | if (!AsyncIoTaskQueue::getInstance().dequeue(&opItem)) { 32 | return; 33 | } 34 | 35 | opItem.taskHandler(); 36 | 37 | auto& asyncEventQueue = asyncpp::task::AsyncTaskQueue::getInstance(); 38 | asyncEventQueue.enqueue({ 39 | .handler = opItem.resumeHandler 40 | }); 41 | } 42 | 43 | void loopMain() { 44 | while (true) { 45 | loopExecution(); 46 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 47 | } 48 | } 49 | 50 | // jthread对象,为I/O线程,jthread让该线程结束之前整个进程都不会结束 51 | std::jthread _thread; 52 | }; 53 | 54 | AsyncIoLoop& AsyncIoLoop::start() { 55 | static AsyncIoLoop ioLoop; 56 | 57 | return ioLoop; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/AsyncIoTask.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:task; 2 | 3 | import asyncpp.core; 4 | import asyncpp.task; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::io { 10 | 11 | export struct AsyncIoTask { 12 | using ResumeHandler = std::function; 13 | using TaskHandler = std::function; 14 | 15 | // 协程唤醒函数 16 | ResumeHandler resumeHandler; 17 | // I/O任务函数 18 | TaskHandler taskHandler; 19 | }; 20 | 21 | export class AsyncIoTaskQueue { 22 | public: 23 | static AsyncIoTaskQueue& getInstance(); 24 | 25 | void enqueue(const AsyncIoTask& item) { 26 | std::lock_guard guard(_queueMutex); 27 | 28 | _queue.push_back(item); 29 | } 30 | 31 | bool dequeue(AsyncIoTask* item) { 32 | std::lock_guard guard(_queueMutex); 33 | 34 | if (_queue.size() == 0) { 35 | return false; 36 | } 37 | 38 | *item = _queue.back(); 39 | _queue.pop_back(); 40 | 41 | return true; 42 | } 43 | 44 | size_t getSize() const { 45 | return _queue.size(); 46 | } 47 | 48 | private: 49 | // I/O任务队列 50 | std::vector _queue; 51 | // I/O任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 52 | std::mutex _queueMutex; 53 | }; 54 | 55 | AsyncIoTaskQueue& AsyncIoTaskQueue::getInstance() { 56 | static AsyncIoTaskQueue queue; 57 | 58 | return queue; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/AsyncIoTask.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io:task; 2 | 3 | import asyncpp.core; 4 | import asyncpp.task; 5 | import ; 6 | import ; 7 | import ; 8 | 9 | namespace asyncpp::io { 10 | 11 | export struct AsyncIoTask { 12 | using ResumeHandler = std::function; 13 | using TaskHandler = std::function; 14 | 15 | // 协程唤醒函数 16 | ResumeHandler resumeHandler; 17 | // I/O任务函数 18 | TaskHandler taskHandler; 19 | }; 20 | 21 | export class AsyncIoTaskQueue { 22 | public: 23 | static AsyncIoTaskQueue& getInstance(); 24 | 25 | void enqueue(const AsyncIoTask& item) { 26 | std::lock_guard guard(_queueMutex); 27 | 28 | _queue.push_back(item); 29 | } 30 | 31 | bool dequeue(AsyncIoTask* item) { 32 | std::lock_guard guard(_queueMutex); 33 | 34 | if (_queue.size() == 0) { 35 | return false; 36 | } 37 | 38 | *item = _queue.back(); 39 | _queue.pop_back(); 40 | 41 | return true; 42 | } 43 | 44 | size_t getSize() const { 45 | return _queue.size(); 46 | } 47 | 48 | private: 49 | // I/O任务队列 50 | std::vector _queue; 51 | // I/O任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 52 | std::mutex _queueMutex; 53 | }; 54 | 55 | AsyncIoTaskQueue& AsyncIoTaskQueue::getInstance() { 56 | static AsyncIoTaskQueue queue; 57 | 58 | return queue; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/Io.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.io; 2 | 3 | export import :loop; 4 | export import :task; 5 | export import :asyncify; -------------------------------------------------------------------------------- /mid_term_exam_sol/src/io/Io.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.io; 2 | 3 | export import :loop; 4 | export import :task; 5 | export import :asyncify; 6 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/AsyncTaskLoop.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:loop; 2 | 3 | import :queue; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export class AsyncTaskLoop { 10 | public: 11 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 12 | static const int32_t SLEEP_MS = 1000; 13 | 14 | static AsyncTaskLoop& getInstance(); 15 | static void start() { 16 | getInstance().startLoop(); 17 | } 18 | 19 | private: 20 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 21 | AsyncTaskLoop() = default; 22 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 23 | AsyncTaskLoop(const AsyncTaskLoop&) = delete; 24 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 25 | AsyncTaskLoop& operator=(const AsyncTaskLoop&) = delete; 26 | 27 | void startLoop() { 28 | while (true) { 29 | loopExecution(); 30 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 31 | } 32 | } 33 | 34 | void loopExecution() { 35 | AsyncTask asyncEvent; 36 | if (!AsyncTaskQueue::getInstance().dequeue(&asyncEvent)) { 37 | return; 38 | } 39 | 40 | asyncEvent.handler(); 41 | } 42 | }; 43 | 44 | AsyncTaskLoop& AsyncTaskLoop::getInstance() { 45 | static AsyncTaskLoop eventLoop; 46 | 47 | return eventLoop; 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/AsyncTaskLoop.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:loop; 2 | 3 | import asyncpp.task.queue; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export class AsyncTaskLoop { 10 | public: 11 | // 常量,定义了任务循环的等待间隔时间(单位为毫秒) 12 | static const int32_t SLEEP_MS = 1000; 13 | 14 | static AsyncTaskLoop& getInstance(); 15 | static void start() { 16 | getInstance().startLoop(); 17 | } 18 | 19 | private: 20 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 21 | AsyncTaskLoop() = default; 22 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 23 | AsyncTaskLoop(const AsyncTaskLoop&) = delete; 24 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 25 | AsyncTaskLoop& operator=(const AsyncTaskLoop&) = delete; 26 | 27 | void startLoop() { 28 | while (true) { 29 | loopExecution(); 30 | std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS)); 31 | } 32 | } 33 | 34 | void loopExecution() { 35 | AsyncTask asyncEvent; 36 | if (!AsyncTaskQueue::getInstance().dequeue(&asyncEvent)) { 37 | return; 38 | } 39 | 40 | asyncEvent.handler(); 41 | } 42 | }; 43 | 44 | AsyncTaskLoop& AsyncTaskLoop::getInstance() { 45 | static AsyncTaskLoop eventLoop; 46 | 47 | return eventLoop; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/AsyncTaskQueue.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task:queue; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export struct AsyncTask { 10 | // 异步任务处理函数类型 11 | using Handler = std::function; 12 | 13 | // 异步任务处理函数 14 | Handler handler; 15 | }; 16 | 17 | export class AsyncTaskQueue { 18 | public: 19 | static AsyncTaskQueue& getInstance(); 20 | 21 | void enqueue(const AsyncTask& item) { 22 | std::lock_guard guard(_queueMutex); 23 | 24 | _queue.push_back(item); 25 | } 26 | 27 | bool dequeue(AsyncTask* item) { 28 | std::lock_guard guard(_queueMutex); 29 | 30 | if (_queue.size() == 0) { 31 | return false; 32 | } 33 | 34 | *item = _queue.back(); 35 | _queue.pop_back(); 36 | 37 | return true; 38 | } 39 | 40 | size_t getSize() const { 41 | return _queue.size(); 42 | } 43 | 44 | private: 45 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 46 | AsyncTaskQueue() = default; 47 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 48 | AsyncTaskQueue(const AsyncTaskQueue&) = delete; 49 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 50 | AsyncTaskQueue& operator=(const AsyncTaskQueue&) = delete; 51 | 52 | // 异步任务队列 53 | std::vector _queue; 54 | // 异步任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 55 | std::mutex _queueMutex; 56 | }; 57 | 58 | AsyncTaskQueue& AsyncTaskQueue::getInstance() { 59 | static AsyncTaskQueue queue; 60 | 61 | return queue; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/AsyncTaskQueue.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task.queue; 2 | 3 | import ; 4 | import ; 5 | import ; 6 | 7 | namespace asyncpp::task { 8 | 9 | export struct AsyncTask { 10 | // 异步任务处理函数类型 11 | using Handler = std::function; 12 | 13 | // 异步任务处理函数 14 | Handler handler; 15 | }; 16 | 17 | export class AsyncTaskQueue { 18 | public: 19 | static AsyncTaskQueue& getInstance(); 20 | 21 | void enqueue(const AsyncTask& item) { 22 | std::lock_guard guard(_queueMutex); 23 | 24 | _queue.push_back(item); 25 | } 26 | 27 | bool dequeue(AsyncTask* item) { 28 | std::lock_guard guard(_queueMutex); 29 | 30 | if (_queue.size() == 0) { 31 | return false; 32 | } 33 | 34 | *item = _queue.back(); 35 | _queue.pop_back(); 36 | 37 | return true; 38 | } 39 | 40 | size_t getSize() const { 41 | return _queue.size(); 42 | } 43 | 44 | private: 45 | // 支持单例模式,通过default修饰符说明构造函数使用默认版本 46 | AsyncTaskQueue() = default; 47 | // 支持单例模式,通过delete修饰符说明拷贝构造函数不可调用 48 | AsyncTaskQueue(const AsyncTaskQueue&) = delete; 49 | // 支持单例模式,通过delete修饰符说明赋值操作符不可调用 50 | AsyncTaskQueue& operator=(const AsyncTaskQueue&) = delete; 51 | 52 | // 异步任务队列 53 | std::vector _queue; 54 | // 异步任务队列互斥锁,用于实现线程同步,确保队列操作的线程安全 55 | std::mutex _queueMutex; 56 | }; 57 | 58 | AsyncTaskQueue& AsyncTaskQueue::getInstance() { 59 | static AsyncTaskQueue queue; 60 | 61 | return queue; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/Task.cpp: -------------------------------------------------------------------------------- 1 | export module asyncpp.task; 2 | 3 | export import :queue; 4 | export import :loop; 5 | export import :coroutine; 6 | export import :asyncify; -------------------------------------------------------------------------------- /mid_term_exam_sol/src/task/Task.ixx: -------------------------------------------------------------------------------- 1 | export module asyncpp.task; 2 | 3 | export import asyncpp.task.queue; 4 | export import :loop; 5 | export import :coroutine; 6 | export import :asyncify; 7 | --------------------------------------------------------------------------------