一个基于现代 C++23 Modules 的传统文化算法库,使用纯模块化设计实现(包含大六壬、六爻、紫薇斗数、八字、奇门遁甲)
ZhouYiLab - 周易实验室
一个基于现代 C++23 Modules 的传统文化算法库,使用纯模块化设计实现
github链接
https://github.com/banderzhm/ZhouYiLab
📖 项目简介
ZhouYiLab 致力于用现代化的编程方式实现和研究传统周易文化相关的算法,包括:
- 🔮 大六壬 - 古代占卜术数之一
- 📿 六爻 - 周易卦象推演系统
- ⭐ 紫微斗数 - 传统命理学
- 🎴 八字排盘 - 四柱命理计算
- 🎯 奇门遁甲 - 古代奇门排盘术数
- 📅 农历历法 - 公历农历互转、节气、干支等
✨ 核心特性
🚀 完全模块化设计
- ✅ 零传统头文件:所有依赖使用
import语句 - ✅ C++23 标准库模块:
import std; - ✅ 第三方库模块化:
import fmt;- 现代格式化输出import magic_enum;- 编译期枚举反射import nlohmann.json;- JSON 序列化
- ✅ 自定义模块系统:所有业务代码使用
.cppm模块接口文件
🏗️ 现代构建系统
- CMake 4.1.2+:完整支持 C++ Modules
FILE_SET CXX_MODULES模块管理CXX_MODULE_GENERATION_MODE SEPARATE编译优化CMAKE_EXPERIMENTAL_CXX_IMPORT_STD标准库模块支持
- Git Submodules:精确管理第三方依赖版本
- 跨平台构建:统一的构建体验(Windows、Linux、macOS)
🎯 严格的代码规范
- 强制 C++23:充分利用最新语言特性
- 模块优先:纯模块化架构,告别传统头文件
- Ranges 优先:使用现代标准库算法
- std::expected:优雅的错误处理
- std::println:统一的输出接口
🔧 构建要求
必需工具
- CMake 4.1.2+(推荐)或 CMake 3.30+(最低兼容版本)
- 支持 C++23 modules 和
import std;的编译器:- GCC 14+ ✅ 完全支持
- Clang 18+ ✅ 完全支持
- MSVC 2022 17.10+ ⚠️ 实验性支持(需要最新版本)
第三方依赖
本项目使用以下第三方库(通过 Git 子模块管理):
| 库 | 版本 | 功能 | 模块支持 |
|---|---|---|---|
| fmt | Latest | 现代化格式化输出、彩色输出 | ✅ import fmt; |
| magic_enum | Latest | 编译期枚举反射,零开销 | ✅ import magic_enum; |
| nlohmann/json | Latest | JSON 序列化/反序列化 | ✅ import nlohmann.json; |
| tyme4cpp | Latest | 强大的日历工具库,支持农历、干支、节气 | 🔄 通过 ZhouYi.LunarCalendar 模块封装 |
🚀 快速开始
1️⃣ 克隆项目
# 克隆项目(包含子模块)
git clone --recursive https://github.com/banderzhm/ZhouYiLab.git
cd ZhouYiLab
如果已经克隆但没有子模块:
git submodule update --init --recursive
2️⃣ 构建项目
Windows (使用 Visual Studio)
cmake -B build -G "Visual Studio 17 2022"
cmake --build build --config Release
Linux / macOS
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
3️⃣ 运行示例
# 基本运行
./build/bin/ZhouYiLab# 运行完整的 C++23 modules 演示
./build/bin/ZhouYiLab --demo# 运行八字示例
./build/bin/example_ba_zi# 运行大六壬示例
./build/bin/example_da_liu_ren# 运行六爻示例
./build/bin/example_liu_yao# 运行奇门遁甲示例
./build/bin/example_qi_men# 运行紫微斗数示例
./build/bin/example_zi_wei
程序将展示:
- 使用
import std;的现代 C++ 代码 - 自定义模块(天干、地支、干支)
- 六十甲子表
- 纳音五行计算
- 各术数系统的完整排盘演示
📁 项目结构
ZhouYiLab/
├── 3rdparty/ # 第三方库(Git 子模块)
│ ├── fmt/ # 格式化库(支持 import fmt;)
│ ├── magic_enum/ # 枚举反射库(支持 import magic_enum;)
│ ├── nlohmann_json/ # JSON 库(支持 import nlohmann.json;)
│ └── tyme4cpp/ # 农历日历库(通过模块包装)
├── cmake/ # CMake 工具链配置
│ ├── clang.toolchain.cmake # Clang 工具链
│ ├── gcc.toolchain.cmake # GCC 工具链
│ └── vs.toolchain.cmake # MSVC 工具链
├── src/ # 源代码(纯模块化)
│ ├── common/ # 通用模块
│ │ ├── tian_gan/ # 天干地支系统
│ │ │ ├── ganzhi.cppm # 完整干支系统(核心)
│ │ │ ├── ba_zi_base.cppm # 八字基础定义
│ │ │ └── wu_xing_utils.cppm # 五行工具
│ │ ├── tyme/ # 农历历法封装
│ │ │ ├── tyme.cpp # tyme4cpp 封装实现
│ │ │ └── tyme_def.cppm # tyme 模块定义
│ │ └── utils/ # 通用工具
│ ├── ba_zi/ # 八字模块
│ │ ├── ba_zi.cppm # 八字核心算法
│ │ ├── ba_zi_controller.cppm # 八字控制器接口
│ │ └── ba_zi_controller.cpp # 八字控制器实现
│ ├── da_liu_ren/ # 大六壬模块
│ ├── liu_yao/ # 六爻模块
│ ├── qi_men/ # 奇门遁甲模块
│ ├── zi_wei/ # 紫微斗数模块
│ └── main.cpp # ⚠️ 唯一允许的 .cpp 文件
├── examples/ # 示例程序
│ ├── example_ba_zi.cpp # 八字系统示例
│ ├── example_da_liu_ren.cpp # 大六壬示例
│ ├── example_liu_yao.cpp # 六爻示例
│ ├── example_qi_men.cpp # 奇门遁甲示例
│ └── example_zi_wei.cpp # 紫微斗数示例
├── tests/ # 单元测试
├── docs/ # 文档
├── CMakeLists.txt # CMake 主配置
├── .gitmodules # Git 子模块配置
└── README.md # 本文档
模块依赖关系
main.cpp├─→ import fmt; (第三方库:格式化输出)├─→ import magic_enum; (第三方库:枚举反射)├─→ import nlohmann.json; (第三方库:JSON)├─→ import ZhouYi.GanZhi; (自定义模块:完整干支系统 核心)├─→ import ZhouYi.LunarCalendar; (自定义模块:农历日历)└─→ import std; (标准库,最后导入!)ZhouYi.GanZhi 核心干支模块├─→ import magic_enum; (反射支持)└─→ import std; (标准库,最后导入)功能:- 天干地支枚举定义- 五行阴阳属性- 生克制化关系- 冲合刑害判断- 六十甲子系统- 纳音五行- 贵人寄宫等ZhouYi.BaZiBase (八字基础模块)├─→ import ZhouYi.GanZhi; (依赖干支系统)└─→ import std;功能:- 八字四柱定义(年月日时)- 十神关系计算- 神煞系统- 大运流年计算ZhouYi.BaZi (八字核心算法)├─→ import ZhouYi.BaZiBase; (基础定义)├─→ import ZhouYi.GanZhi; (干支系统)├─→ import ZhouYi.Tyme; (农历历法)└─→ import std;功能:- 公历/农历排盘- 童限计算- 大运起运- 流年流月推算ZhouYi.BaZiController (八字控制器)├─→ import ZhouYi.BaZi; (核心算法)├─→ import fmt; (格式化输出)└─→ import std;功能:- 排盘接口封装- 结果格式化显示- 交互式排盘ZhouYi.DaLiuRen (大六壬模块)├─→ import ZhouYi.GanZhi; (干支系统)├─→ import ZhouYi.Tyme; (农历历法)├─→ import nlohmann.json; (JSON序列化)└─→ import std;功能:- 天地盘系统(月将、贵人、十二神将)- 四课计算(干上神、支上神、阴神、阳神)- 三传取法(贼克、比用、涉害、遥克等)- 神煞系统- 卦体判断- 课式分类ZhouYi.QiMen (奇门遁甲模块)├─→ import ZhouYi.GanZhi; (干支系统)├─→ import ZhouYi.Tyme; (农历历法)└─→ import std;功能:- 阴阳遁算法(阳遁九局、阴遁九局)- 节气自动识别- 九宫排盘(天盘、地盘、人盘)- 八门配置(休、生、伤、杜、景、死、惊、开)- 九星配置(天蓬、天芮、天冲、天辅、天禽、天心、天柱、天任、天英)- 八神配置(值符、腾蛇、太阴、六合、白虎、玄武、九地、九天)- 吉凶分析ZhouYi.LiuYao (六爻模块)├─→ import ZhouYi.BaZiBase; (八字基础)├─→ import ZhouYi.WuXingUtils; (五行工具)├─→ import ZhouYi.DiZhiRelations; (地支关系)├─→ import fmt; (格式化输出)├─→ import nlohmann.json; (JSON序列化)└─→ import std;功能:- 纳甲装卦(本卦、变卦、伏神)- 六亲关系计算- 六神配置(青龙、朱雀、勾陈、螣蛇、白虎、玄武)- 世应标记- 旺衰判定- 神煞系统ZhouYi.ZiWei (紫微斗数模块)├─→ import ZhouYi.GanZhi; (干支系统)├─→ import ZhouYi.Tyme; (农历历法)└─→ import std;功能:- 命盘排盘- 十二宫位- 主星安星- 辅星配置- 四化计算
💡 使用示例
🎴 八字排盘
import ZhouYi.BaZiController;
import ZhouYi.GanZhi;
import ZhouYi.ZhMapper;
import std;using namespace ZhouYi::BaZiController;
using namespace ZhouYi::GanZhi;
using namespace ZhouYi::Mapper;// 方式1:公历排盘
auto result = pai_pan_solar(2000, 7, 15, 16, 30, true); // 最后参数:true=男,false=女// 方式2:农历排盘
auto result_lunar = pai_pan_lunar(2000, 6, 15, 16, 30, true);// 访问八字信息
const auto& ba_zi = result.ba_zi;
std::println("年柱:{}", ba_zi.year.to_string()); // 庚辰
std::println("月柱:{}", ba_zi.month.to_string()); // 癸未
std::println("日柱:{}", ba_zi.day.to_string()); // 甲申
std::println("时柱:{}", ba_zi.hour.to_string()); // 壬申// 查看十神关系
auto shi_shen_year = get_shi_shen(ba_zi.day.gan, ba_zi.year.gan);
std::println("年干对日干:{}", to_zh(shi_shen_year)); // 偏财auto shi_shen_month = get_shi_shen(ba_zi.day.gan, ba_zi.month.gan);
std::println("月干对日干:{}", to_zh(shi_shen_month)); // 伤官// 查看童限信息
std::println("童限:{}", result.child_limit.to_string());
std::println("起运岁数:{}", result.start_age);
std::println("起运方向:{}", result.is_shun_pai ? "顺排" : "逆排");// 查看大运
for (size_t i = 0; i < 5 && i < result.da_yun_list.size(); ++i) {const auto& da_yun = result.da_yun_list[i];std::println("大运{}: {} ({}岁-{}岁)", i + 1, da_yun.gan_zhi.to_string(),da_yun.start_age,da_yun.end_age);
}// 查看流年
auto liu_nian_2025 = get_liu_nian(result, 2025);
std::println("2025年流年:{}", liu_nian_2025.gan_zhi.to_string());// 查看流月
auto liu_yue_list = get_liu_yue_list(result, 2025);
for (const auto& liu_yue : liu_yue_list) {std::println("{}月:{}", liu_yue.month, liu_yue.gan_zhi.to_string());
}// 格式化显示完整结果
display_result(result);// 显示详细的童限和大运信息
display_child_limit_detail(result);
display_da_yun(result, 10); // 显示前10个大运// 显示流年信息
display_liu_nian(result, 2020, 10); // 从2020年开始显示10年// 显示流月信息
display_liu_yue(result, 2025); // 显示2025年的12个月
八字模块功能特性:
- ✅ 完整的四柱排盘(年月日时)
- ✅ 公历/农历自动转换(基于 tyme4cpp)
- ✅ 十神关系计算(比肩、劫财、食神、伤官、偏财、正财、七杀、正官、偏印、正印)
- ✅ 神煞系统(贵人、驿马、桃花、禄神等)
- ✅ 童限计算(起运岁数、顺逆排)
- ✅ 大运推算(10年一运)
- ✅ 流年流月推算
- ✅ 格式化输出和交互式排盘
🔮 大六壬排盘
import ZhouYi.DaLiuRen;
import ZhouYi.DaLiuRen.Controller;
import std;using namespace ZhouYi::DaLiuRen;// 方式1:使用排盘引擎(非交互式)
auto result = DaLiuRenEngine::pai_pan(2024, 10, 13, 14); // 公历// 方式2:从农历排盘
auto result_lunar = DaLiuRenEngine::pai_pan_lunar(2024, 9, 11, 7);// 方式3:交互式排盘(控制台输入)
Controller::DaLiuRenController::interactive_pai_pan();// 访问排盘结果
std::println("月将: {}", result.yue_jiang);
std::println("贵人: {}", result.gui_ren);// 获取四课信息
const auto& si_ke = result.si_ke;
std::println("第一课: {}", si_ke.first.to_string());
std::println("第二课: {}", si_ke.second.to_string());
std::println("第三课: {}", si_ke.third.to_string());
std::println("第四课: {}", si_ke.fourth.to_string());// 获取三传信息
const auto& san_chuan = result.san_chuan;
std::println("初传: {}", san_chuan.get_chu_chuan());
std::println("中传: {}", san_chuan.get_zhong_chuan());
std::println("末传: {}", san_chuan.get_mo_chuan());
std::println("课式: {}", san_chuan.get_ke_shi());// 获取天地盘信息
const auto& tian_di_pan = result.tian_di_pan;
auto tian_pan = tian_di_pan.get_tian_pan();
auto di_pan = tian_di_pan.get_di_pan();// 显示格式化结果
Controller::DaLiuRenController::display_result_detailed(result);// 导出为 JSON
nlohmann::json json_result = result.to_json();
std::println("{}", json_result.dump(2));
大六壬模块功能特性:
- ✅ 完整的天地盘系统(月将、贵人、十二神将)
- ✅ 四课计算(干上神、支上神、阴神、阳神)
- ✅ 三传取法(贼克、比用、涉害、遥克、昴星、别责等)
- ✅ 神煞系统(完整的神煞判定)
- ✅ 卦体判断(蒿矢、重审、元首等)
- ✅ 课式分类(九宗门、十二神将课等)
📿 六爻排盘
import ZhouYi.LiuYaoController;
import ZhouYi.BaZiBase;
import std;using namespace ZhouYi::LiuYaoController;
using namespace ZhouYi::BaZiBase;// 创建八字(用于计算旺衰、神煞)
auto bazi = BaZi::from_solar(2024, 10, 13, 14, 30);// 方式1:直接使用主卦代码排盘
// 主卦代码:"010101"(6位二进制,'0'=阴爻,'1'=阳爻,从下到上)
// 动爻:第3爻和第5爻动
auto result = calculate_liu_yao("010101", bazi, {3, 5});// 方式2:从爻辞生成主卦代码
std::vector<int> yao_ci = {7, 8, 6, 9, 7, 8}; // 从下到上
// 6=老阴(动), 7=少阳, 8=少阴, 9=老阳(动)
std::vector<int> changing_lines;
auto code = yao_ci_to_hexagram_code(yao_ci, changing_lines);
auto result2 = calculate_liu_yao(code, bazi, changing_lines);// 方式3:从数字卦生成(金钱卦、梅花易数等)
std::vector<int> numbers = {3, 2, 3, 1, 2, 3}; // 从下到上
auto code3 = numbers_to_hexagram_code(numbers, true); // true=奇数为阳爻
auto result3 = calculate_liu_yao(code3, bazi);// 访问排盘结果
std::println("卦象信息:");
for (const auto& yao : result.yao_list) {std::println("第{}爻:", yao.position);std::println(" 本卦: {} {} {}", yao.mainRelative, // 六亲yao.mainPillar.to_string(), // 纳甲干支yao.mainElement); // 五行if (yao.isChanging) {std::println(" 变爻: {} {} {}", yao.changedRelative,yao.changedPillar.to_string(),yao.changedElement);}std::println(" 六神: {}", yao.spirit);std::println(" 旺衰: {}", yao.wangShuai);std::println(" 世应: {}", yao.shiYingMark);
}// 获取卦象基本信息(不进行完整排盘)
auto hexagram_info = get_hexagram_info("010101");
std::println("卦名: {}", hexagram_info.name);
std::println("卦义: {}", hexagram_info.meaning);
std::println("五行: {}", hexagram_info.fiveElement);
std::println("世爻: {}, 应爻: {}", hexagram_info.shiYaoPosition, hexagram_info.yingYaoPosition);// 批量排盘
std::vector<std::tuple<std::string, BaZi, std::vector<int>>> batch_requests = {{"010101", bazi, {3, 5}},{"111000", bazi, {1}},{"000111", bazi, {}}
};
auto batch_results = batch_calculate_liu_yao(batch_requests);// 导出为 JSON
std::println("{}", result.json_data.dump(2));
六爻模块功能特性:
- ✅ 完整的纳甲装卦(本卦、变卦、伏神)
- ✅ 六亲关系计算(兄弟、子孙、妻财、官鬼、父母)
- ✅ 六神配置(青龙、朱雀、勾陈、螣蛇、白虎、玄武)
- ✅ 世应标记(自动识别世爻、应爻位置)
- ✅ 旺衰判定(基于月令五行)
- ✅ 神煞系统(日禄、贵人、驿马、桃花等)
- ✅ 多种起卦方式(二进制码、爻辞、数字卦)
📅 农历日历功能
import ZhouYi.LunarCalendar;
import std;// 从公历创建
auto solar = ZhouYi::Lunar::SolarDate::from_ymd(1986, 5, 29);
auto lunar = solar.to_lunar();// 获取农历信息
std::println("农历: {}", lunar.to_string()); // 农历甲寅年四月廿一
std::println("年干支: {}", lunar.get_year_gan_zhi()); // 丙寅
std::println("生肖: {}", lunar.get_zodiac()); // 虎// 从农历创建
auto lunar2 = ZhouYi::Lunar::LunarDate::from_lunar(2025, 1, 1);
auto [y, m, d] = lunar2.to_solar(); // 转换为公历// 二十四节气
auto terms = ZhouYi::Lunar::SolarTerm::get_terms_of_year(2025);
for (const auto& [name, date] : terms) {std::println("{}: {}", name, date);
}
基于 tyme4cpp 库实现。
🎴 完整干支系统
import ZhouYi.GanZhi;
using namespace ZhouYi::GanZhi;// 定义天干地支
auto jia = TianGan::Jia;
auto zi = DiZhi::Zi;// 获取中文名称
auto name = Mapper::to_zh(jia); // "甲"// 获取五行属性
auto wu_xing = get_wu_xing(jia); // WuXing::Mu (木)
auto yin_yang = get_yin_yang(jia); // YinYang::Yang (阳)// 判断地支关系
bool chong = is_chong(DiZhi::Zi, DiZhi::Wu); // 子午相冲
bool he = is_he(DiZhi::Zi, DiZhi::Chou); // 子丑相合
bool xing = is_xing(DiZhi::Zi, DiZhi::Mao); // 子卯相刑// 地支三合
auto [is_san_he, he_wx] = is_san_he(DiZhi::Shen, DiZhi::Zi, DiZhi::Chen
); // 申子辰合水局// 五行生克
bool sheng = wu_xing_sheng(WuXing::Mu, WuXing::Huo); // 木生火
bool ke = wu_xing_ke(WuXing::Mu, WuXing::Tu); // 木克土// 六十甲子
auto jz = LiuShiJiaZi::from_index(0); // 甲子
auto na_yin = jz.get_na_yin(); // 获取纳音五行// 天干贵人
auto gui = get_gui_ren(TianGan::Jia, true); // 甲日阳贵人// 天干寄宫
auto gong = get_ji_gong(TianGan::Jia); // 甲寄寅宫// 地支藏干
auto cang = get_cang_gan(DiZhi::Yin); // 寅藏甲丙戊
完整的模块功能包括:
- ✅ 完整的枚举定义和运算符重载
- ✅ 五行阴阳属性查询
- ✅ 生克制化关系判断
- ✅ 冲合刑害完整判断
- ✅ 六十甲子系统(含纳音)
- ✅ 贵人寄宫藏干等高级功能
🎯 奇门遁甲排盘
import ZhouYi.QiMen.Controller;
import ZhouYi.QiMen;
import std;using namespace ZhouYi::QiMen;// 方式1:公历排盘
auto result = QiMenController::pai_pan_solar(2011, 6, 18, 3, 56);
if (result) {const auto& pan = result.value();std::println("阴阳遁:{}", pan.dun == Dun::Yang ? "阳遁" : "阴遁");std::println("局数:第{}局", pan.ju);std::println("节气:{}", pan.solar_term);std::println("日干支:{}", pan.day_gan_zhi.to_string());std::println("时干支:{}", pan.hour_gan_zhi.to_string());
} else {std::println("排盘失败:{}", result.error());
}// 方式2:农历排盘
auto result_lunar = QiMenController::pai_pan_lunar(2023, 5, 5, 14, 30);// 获取排盘摘要
if (result) {const auto& pan = result.value();auto summary = QiMenAnalyzer::get_summary(pan);std::println("{}", summary);
}// 分析宫位吉凶
if (result) {const auto& pan = result.value();// 分析南宫(离九宫)auto analysis = QiMenAnalyzer::analyze_auspiciousness(pan, Palace::South);if (analysis) {std::println("南宫分析:\n{}", analysis.value());}// 分析其他宫位auto north_analysis = QiMenAnalyzer::analyze_auspiciousness(pan, Palace::North);auto east_analysis = QiMenAnalyzer::analyze_auspiciousness(pan, Palace::East);auto west_analysis = QiMenAnalyzer::analyze_auspiciousness(pan, Palace::West);
}// 查看九宫信息
if (result) {const auto& pan = result.value();// 遍历九宫for (const auto& [palace, gong_info] : pan.gong_map) {std::println("宫位:{}", palace);std::println("天盘:{}", gong_info.tian_pan);std::println("地盘:{}", gong_info.di_pan);std::println("人盘:{}", gong_info.ren_pan);std::println("八门:{}", gong_info.ba_men);std::println("九星:{}", gong_info.jiu_xing);std::println("八神:{}", gong_info.ba_shen);std::println();}
}
奇门遁甲模块功能特性:
- ✅ 完整的阴阳遁算法(阳遁九局、阴遁九局)
- ✅ 公历/农历自动转换(基于 tyme4cpp)
- ✅ 自动获取节气和干支信息
- ✅ 九宫排盘(天盘、地盘、人盘)
- ✅ 八门配置(休、生、伤、杜、景、死、惊、开)
- ✅ 九星配置(天蓬、天芮、天冲、天辅、天禽、天心、天柱、天任、天英)
- ✅ 八神配置(值符、腾蛇、太阴、六合、白虎、玄武、九地、九天)
- ✅ 吉凶分析功能
- ✅ 格式化输出和摘要生成
📋 开发规范
1️⃣ C++23 标准强制
所有代码必须使用 C++23 特性:
- ✅
std::expected、std::optional、std::mdspan - ✅ Ranges 和 Views(
std::ranges、std::views) - ✅
std::print/std::println - ✅ 概念和约束(
concept、requires)
2️⃣ 模块化规范
- 强制使用模块:除
main.cpp外,所有源文件必须使用.cppm扩展名 - 导入顺序规范:
// 1. 第三方库模块 import fmt; import magic_enum; import nlohmann.json;// 2. 自定义模块 import ZhouYi.GanZhi; import ZhouYi.LunarCalendar;// 3. 标准库(必须最后!) import std; - 禁止混用头文件:本项目采用纯模块化设计
3️⃣ 算法规范
优先使用 Ranges:所有容器操作优先使用 std::ranges 算法
✅ 推荐:
std::ranges::transform(vec, std::back_inserter(result), fn);
std::ranges::filter(vec, predicate);
std::ranges::for_each(vec, action);
std::ranges::find_if(vec, condition);
std::ranges::count_if(vec, predicate);
std::ranges::any_of(vec, predicate);
❌ 避免:
std::transform(vec.begin(), vec.end(), ...); // 传统算法
for (auto& item : vec) { ... } // 手写循环(除非必要)
4️⃣ 输出规范
统一使用 std::println:禁止使用其他输出方式
✅ 推荐:
std::println("{}", value); // 带换行
std::print("{}", value); // 不换行
❌ 禁止:
std::cout << value << std::endl; // 禁止
printf("%d", value); // 禁止
fmt::print("{}", value); // 禁止
5️⃣ 错误处理规范
优先使用 std::expected:可恢复的错误使用 std::expected<T, E>
✅ 推荐:
// 函数返回值可能失败时
std::expected<Result, Error> process_data() {if (error_condition) {return std::unexpected(Error{"错误信息"});}return Result{...};
}// 可选值
std::optional<Value> find_value() {if (found) return value;return std::nullopt;
}
❌ 避免:
Result* process_data(); // 返回 nullptr
int process_data(Result& out); // 返回错误码
throw std::exception("error"); // 使用异常(除非必要)
🐛 常见问题
Q: 为什么import std; 必须放在最后?
A: 标准库模块会导出大量符号,如果先导入 std,可能与第三方库的内部实现产生冲突。特别是 nlohmann::json 内部使用了传统头文件,会导致符号重定义错误。
.h 头文件和模块吗?
A: 不可以。本项目采用纯模块化设计,所有代码必须使用模块系统。这确保了编译性能和符号隔离。
Q: MSVC 提示warning C5050 怎么办?
A: 这是 MSVC 的已知警告,已在 CMakeLists.txt 中使用 /wd5050 抑制,不影响编译。
A: 这是 C++ Modules 的当前限制。建议:
- 使用增量编译(默认已启用)
- 使用 Ninja 构建系统(比 Make 快)
- 启用编译缓存(ccache/sccache)
- 使用多核编译
cmake --build build -j$(nproc)
🔧 项目维护
更新第三方库
# 更新所有子模块到最新版本
git submodule update --remote --merge# 更新指定子模块
git submodule update --remote --merge 3rdparty/fmt
清理构建
# 完全清理
rm -rf build/# 重新构建
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
🤝 贡献指南
欢迎贡献代码!请确保:
- ✅ 遵守上述所有开发规范
- ✅ 代码通过编译且无警告
- ✅ 提交前运行格式化工具
- ✅ 提供清晰的提交信息
# 提交代码模板
git add .
git commit -m "feat(module): 添加新的天干地支计算模块"
git push
📚 相关资源
官方文档
- C++23 Modules 官方文档
- CMake Modules 支持
- C++23 特性概览
第三方库文档
- fmt 库文档 - 现代格式化输出
- magic_enum 库文档 - 编译期枚举反射
- nlohmann/json 文档 - JSON 序列化
- tyme4cpp 库文档 - 强大的日历工具库
学习资源
- magic_enum 示例
- C++23 Ranges 教程
📄 许可证
本项目采用 MIT 许可证 - 详见 LICENSE 文件
⚡ 技术栈
C++23 | CMake 4.1.2 | Git Submodules | Pure Modules Design | Compile-time Reflection
打造现代化的传统文化算法库 🌟
