<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Topics tagged with c++]]></title><description><![CDATA[A list of topics that have been tagged with c++]]></description><link>http://forum.d2learn.org/tags/c++</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Jul 2026 14:11:07 GMT</lastBuildDate><atom:link href="http://forum.d2learn.org/tags/c++.rss" rel="self" type="application/rss+xml"/><pubDate>Invalid Date</pubDate><ttl>60</ttl><item><title><![CDATA[[mcpp]: 用 C++23 模块 + import std 开发了个构建工具，并实现自己构建自己(自举)]]></title><description><![CDATA[<p dir="auto">从去年 gcc 15.1 初步支持 import std 开始, 我就在 C++的模块化上做了很多实践</p>
<p dir="auto">前段时间, 突然产生了以 C++23 模块化为基础, <strong>实现一个现代 C++模块化项目的构建工具</strong>。并以其能用自己从源码构建出自己也就是所谓的<strong>自举来做为初步目标</strong>, 目前这个目标已经实现</p>
<p dir="auto">欢迎对现代 C++和模块化感兴趣的朋友来用, mcpp 构建工具使用模块化特性 玩一玩或开发开发小项目 也欢迎大家来反馈和交流</p>
<p dir="auto"><strong>开源仓库:</strong> <a href="https://github.com/mcpp-community/mcpp" rel="nofollow ugc">https://github.com/mcpp-community/mcpp</a></p>
<hr />
<h1>mcpp</h1>
<blockquote>
<p dir="auto">一个 现代 C++ 模块化构建工具 — 纯 C++23 模块编写，已实现自举</p>
</blockquote>
<h2>核心特性</h2>
<ul>
<li><strong>C++23 模块原生支持</strong> — <code>import std</code> 自动处理，文件级增量构建，模块依赖自动分析，零手动配置</li>
<li><strong>纯模块化自举</strong> — mcpp 自身由 43+ 个 C++23 模块组成，用自己构建自己，模块系统经实战验证</li>
<li><strong>开箱即用</strong> — 一条命令安装，内置 GCC 16 / LLVM 20 工具链，自动下载到隔离沙盒，不污染系统</li>
<li><strong>集成依赖管理</strong> — SemVer 约束解析、锁文件、跨项目 BMI 缓存、自定义包索引</li>
<li><strong>多包工作空间</strong> — Workspace 统一锁文件与版本管理，适合大型项目</li>
</ul>
<h2>为什么选择 mcpp ?</h2>
<p dir="auto">mcpp 专门为 <strong>C++23 模块化开发</strong> 打造。如果你想在项目中使用 <code>import std</code>、模块接口单元（<code>.cppm</code>）、模块分区等现代 C++ 特性，mcpp 在 Linux 上能为你提供便捷且友好的开发体验：</p>
<ul>
<li><strong>默认模块化</strong> — <code>mcpp new</code> 创建的项目模板直接使用 C++23 模块，<code>import std</code> 开箱即用</li>
<li><strong>文件级增量构建</strong> — 基于 P1689 dyndep 的三层优化（前端脏检查 + 逐文件扫描 + BMI restat ），只重编真正变化的模块</li>
<li><strong>一键创建 &amp; 构建</strong> — <code>mcpp new hello &amp;&amp; cd hello &amp;&amp; mcpp build</code>，工具链自动安装，无需手动配置编译器和构建系统</li>
<li><strong>模块化生态</strong> — <a href="https://github.com/mcpplibs" rel="nofollow ugc">mcpplibs</a> 提供一系列可直接 <code>import</code> 的 C++ 模块化库，支持自定义包索引</li>
</ul>
<blockquote>
<p dir="auto">注: <strong>早期版本</strong> — mcpp 仍在积极开发中，接口和行为可能在后续版本调整。<br />
欢迎对现代 C++ 模块化构建工具感兴趣的开发者<a href="#%E5%8F%82%E4%B8%8E%E8%B4%A1%E7%8C%AE">参与贡献</a>。<br />
问题 / 反馈 / 想法欢迎在 <a href="https://github.com/mcpp-community/mcpp/issues" rel="nofollow ugc">issues</a> 留言。</p>
</blockquote>
<h2>快速开始</h2>
<h3>安装</h3>
<p dir="auto"><strong>方式一：使用 xlings 安装（推荐）</strong></p>
<pre><code class="language-bash">xlings install mcpp -y
</code></pre>
<p dir="auto"><strong>方式二：一键安装脚本</strong></p>
<pre><code class="language-bash">curl -fsSL https://github.com/mcpp-community/mcpp/releases/latest/download/install.sh | bash
</code></pre>
<p dir="auto">安装到 <code>~/.mcpp/</code>，自动加进 shell PATH 。删除 <code>~/.mcpp</code> 即可干净卸载。</p>
<p dir="auto"><strong>方式三：让 AI 助手帮你安装</strong></p>
<p dir="auto">将以下提示词复制给你的 AI 编码助手（ Claude Code / Cursor / Copilot 等）：</p>
<pre><code>阅读 https://github.com/mcpp-community/mcpp 的 README ，
帮我安装 mcpp 并创建一个 C++23 模块项目，构建并运行。
项目的 .agents/skills/mcpp-usage/SKILL.md 有详细的使用指南。
</code></pre>
<h3>创建项目 &amp; 构建运行</h3>
<pre><code class="language-bash">mcpp new hello
cd hello
mcpp build
mcpp run
</code></pre>
<blockquote>
<p dir="auto">注：首次构建会初始化环境并获取工具链，可能需要一些时间。</p>
</blockquote>
<h3>项目结构</h3>
<pre><code>hello/
├── mcpp.toml             ← 工程描述
└── src/
    └── main.cpp          ← import std; 直接可用
</code></pre>
<pre><code class="language-toml"># mcpp.toml
[package]
name = "hello"

[targets.hello]
kind = "bin"
main = "src/main.cpp"
</code></pre>
<h3>使用模块化库</h3>
<p dir="auto">在 <code>mcpp.toml</code> 中添加两行依赖，即可引用 <a href="https://github.com/mcpplibs" rel="nofollow ugc">mcpplibs</a> 社区模块化库：</p>
<pre><code class="language-toml">[dependencies]
cmdline = "0.0.2"
</code></pre>
<p dir="auto">然后在代码中直接 <code>import</code>：</p>
<pre><code class="language-cpp">import mcpplibs.cmdline;
</code></pre>
<blockquote>
<p dir="auto">更多依赖配置方式（版本约束、命名空间、Git 引用、本地路径等）参见 <a href="docs/05-mcpp-toml.md">mcpp.toml 指南 — 依赖管理</a>。</p>
</blockquote>
<h2>平台支持</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>OS / arch</th>
<th style="text-align:center">GCC (glibc)</th>
<th style="text-align:center">GCC (musl)</th>
<th style="text-align:center">Clang / LLVM</th>
<th style="text-align:center">MSVC</th>
</tr>
</thead>
<tbody>
<tr>
<td>Linux x86_64</td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title=":white_check_mark:" alt="✅" /></td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title=":white_check_mark:" alt="✅" /> <em>默认</em></td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title=":white_check_mark:" alt="✅" /></td>
<td style="text-align:center">—</td>
</tr>
<tr>
<td>Linux aarch64</td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
<td style="text-align:center">—</td>
</tr>
<tr>
<td>macOS</td>
<td style="text-align:center">—</td>
<td style="text-align:center">—</td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
<td style="text-align:center">—</td>
</tr>
<tr>
<td>Windows</td>
<td style="text-align:center">—</td>
<td style="text-align:center">—</td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
<td style="text-align:center"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /></td>
</tr>
</tbody>
</table>
<p dir="auto"><img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title=":white_check_mark:" alt="✅" /> 已支持 ｜ <img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f504.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--arrows_counterclockwise" style="height:23px;width:auto;vertical-align:middle" title=":arrows_counterclockwise:" alt="🔄" /> 计划中</p>
<blockquote>
<p dir="auto"><em>默认</em>：release 二进制走 musl 全静态，Linux x86_64 可直接运行，无 glibc 依赖。</p>
</blockquote>
<h2>文档</h2>
<ul>
<li><a href="docs/00-getting-started.md">快速开始</a> — 5 分钟完成 install → new → build → run</li>
<li><a href="docs/01-examples.md">示例项目</a></li>
<li><a href="docs/02-pack-and-release.md">发布打包</a></li>
<li><a href="docs/03-toolchains.md">工具链管理</a></li>
<li><a href="docs/04-build-from-source.md">从源码构建</a></li>
<li><a href="docs/05-mcpp-toml.md">mcpp.toml 指南</a></li>
<li><a href="docs/06-workspace.md">工作空间</a></li>
</ul>
<p dir="auto">任意命令的完整选项可通过 <code>mcpp &lt;cmd&gt; --help</code> 查阅。</p>
<p dir="auto"><strong>AI 辅助学习</strong>：你可以将以下提示词发给 AI 编码助手，让它帮你快速了解 mcpp：</p>
<pre><code>阅读 https://github.com/mcpp-community/mcpp 仓库的
.agents/skills/mcpp-usage/SKILL.md 和 docs/ 目录下的文档，
告诉我如何用 mcpp 创建一个带依赖的 C++23 模块项目。
</code></pre>
<h2>参与贡献</h2>
<p dir="auto">欢迎通过 Issue 和 PR 参与项目开发。项目接受开发者使用 AI Agent 参与开发与贡献。</p>
<p dir="auto"><strong>基本流程</strong></p>
<ol>
<li>创建 Issue — Bug 修复、新功能、优化等，先在 <a href="https://github.com/mcpp-community/mcpp/issues" rel="nofollow ugc">issues</a> 创建讨论</li>
<li>实现改动 — Fork 仓库，创建分支，实现并验证（<code>mcpp build</code> + E2E 测试）</li>
<li>提交 PR — 使用 <code>gh pr create</code>，确保 CI 通过</li>
<li>CI 必须通过 — CI 不通过的 PR 不会被合入</li>
</ol>
<p dir="auto"><strong>提交信息规范</strong>：<code>feat:</code> / <code>fix:</code> / <code>test:</code> / <code>docs:</code> / <code>refactor:</code> 前缀</p>
<p dir="auto"><strong>AI Agent 贡献</strong>：项目的 <a href=".agents/skills/mcpp-contributing/SKILL.md"><code>.agents/skills/mcpp-contributing/SKILL.md</code></a> 提供了完整的 Agent 贡献流程和项目结构说明。将以下提示词发给 AI 助手即可：</p>
<pre><code>阅读 https://github.com/mcpp-community/mcpp 仓库的
.agents/skills/mcpp-contributing/SKILL.md ，
按照指南帮我给 mcpp 项目提交一个贡献。
</code></pre>
<h2>社区 &amp; 生态</h2>
<ul>
<li><a href="https://forum.d2learn.org/category/20" rel="nofollow ugc">社区论坛</a> — 交流群 (Q: 1067245099)</li>
<li><a href="https://github.com/mcpp-community/mcpp-index" rel="nofollow ugc">mcpp-index</a> — 默认包索引</li>
<li><a href="https://github.com/mcpplibs" rel="nofollow ugc">mcpplibs</a> — 模块化 C++ 库集合</li>
</ul>
<h3>致谢</h3>
<p dir="auto">项目依赖和灵感来源：</p>
<ul>
<li><a href="https://github.com/d2learn/xlings" rel="nofollow ugc">xlings</a> — 工具链 / 包管理底座</li>
<li><a href="https://github.com/mcpplibs/cmdline" rel="nofollow ugc">mcpplibs.cmdline</a> — CLI 框架</li>
<li><a href="https://github.com/ninja-build/ninja" rel="nofollow ugc">ninja</a> — 底层构建引擎</li>
<li><a href="https://github.com/xmake-io/xmake" rel="nofollow ugc">xmake</a> — 跨平台构建工具</li>
<li><a href="https://github.com/rust-lang/cargo" rel="nofollow ugc">cargo</a> — Rust 包管理器</li>
</ul>
]]></description><link>http://forum.d2learn.org/topic/207/mcpp-用-c-23-模块-import-std-开发了个构建工具-并实现自己构建自己-自举</link><guid isPermaLink="true">http://forum.d2learn.org/topic/207/mcpp-用-c-23-模块-import-std-开发了个构建工具-并实现自己构建自己-自举</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[GCC 16 上手初体验：环境配置、默认 C++20、模块化、诊断增强和 C++26 反射]]></title><description><![CDATA[<h1>GCC 16 上手初体验：环境配置、默认 C++20、模块化、诊断增强和 C++26 反射</h1>
<p dir="auto">从去年发布GCC 15.1 并支持 <code>import std</code>开始, 我的新项目也全面转向<code>C++23 + 模块化</code> (踩了不少坑 [逃]). 而最近几天 GCC 16.1 也正式发布了, 这篇文章就来初步的上手体验一下.</p>
<p dir="auto">主要内容包括:</p>
<ul>
<li>0.GCC 16 环境配置</li>
<li>1.默认标准: 从C++17升级到C++20, 正式进入C++2x时代</li>
<li>2.模块化: 有一定优化, 但任处于实验性支持阶段 (悲)</li>
<li>3.代码诊断和静态分析增强</li>
<li>4.C++ 26 反射实验性支持</li>
<li>5.总结及相关链接</li>
</ul>
<h2>0. 环境配置 (Linux)</h2>
<p dir="auto">安装GCC 16可以选择按官方文档从源码进行构建 <a href="https://gcc.gnu.org/wiki/InstallingGCC" rel="nofollow ugc">GCC WIKI</a> 或 直接使用xlings工具安装预构建版本(注: 该方式有个好处不污染系统环境)</p>
<p dir="auto"><code>安装xlings包管理工具</code></p>
<pre><code class="language-bash">curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/refs/heads/main/tools/other/quick_install.sh | bash
source ~/.bashrc # 或重新打开一次控制台
xlings -h
</code></pre>
<p dir="auto"><code>xlings工具安装后, 创建隔离环境并安装gcc 16</code></p>
<pre><code class="language-bash">xlings subos new gcc-test
xlings subos use gcc-test
xlings install gcc@16.1.0 -y
gcc --version
</code></pre>
<p dir="auto"><img src="/assets/uploads/files/1777910290747-2026-05-04_22-10.png" alt="2026-05-04_22-10.png" class=" img-fluid img-markdown" /></p>
<h2>1.默认标准: 从 C++17 升级到 C++20, 正式进入 C++2x 时代</h2>
<p dir="auto">GCC 16 的一个关键变化是: C++ 编译默认标准从 GNU++17 变成 GNU++20。不用额外再写 <code>-std=c++20</code> 也能编译下面的程序了:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

consteval int answer() {
    return 16;
}

int main() {
    std::cout &lt;&lt; "__cplusplus=" &lt;&lt; __cplusplus
              &lt;&lt; ", consteval=" &lt;&lt; answer() &lt;&lt; '\n';
}
</code></pre>
<p dir="auto">编译运行:</p>
<pre><code class="language-bash">g++ cpp20-default.cpp -o cpp20-default
./cpp20-default
</code></pre>
<p dir="auto">输出:</p>
<pre><code class="language-text">__cplusplus=202002, consteval=16
</code></pre>
<p dir="auto">如果显式退回 C++17:</p>
<pre><code class="language-bash">g++ -std=c++17 cpp20-default.cpp -o cpp17-check
</code></pre>
<p dir="auto">会报错:</p>
<pre><code class="language-cpp">t.cpp:3:1: error: 'consteval' does not name a type; did you mean 'constexpr'?
    3 | consteval int answer() {
      | ^~~~~~~~~
      | constexpr
</code></pre>
<p dir="auto">默认标准的改变, 不仅仅只是帮我们省了<code>-std=c++20</code>，而是默认构建行为的改变 会加速C++ 2x时代生态的发展</p>
<h3>2.模块化: 有一定优化, 但任处于实验性支持阶段</h3>
<p dir="auto">模块化早在C++20就发布, 他的目标是想解决 C++ 头文件模型长期存在的问题: 重复解析、宏污染、包含顺序敏感、接口和实现边界不够清晰。在工程方面他对C++的影响是颠覆性的, 但是由于历史/兼容性/复杂度等多方面原因导致, GCC 16 的默认标准虽然是 GNU++20，但 modules 支持仍然是实验性的，所以GCC 16对模块化爱好者来说只能算波澜不惊</p>
<p dir="auto">只不过, GCC16 还是有在模块化做了一些工作的</p>
<ul>
<li>修复了一些模块化的bug</li>
<li>新增 <code>--compile-std-module</code>，用于更方便地构建标准库相关模块和 header unit</li>
</ul>
<p dir="auto">其中 <code>--compile-std-module</code> 的增加 更方便大家体验模块化和<code>import std</code>, 避免了之前连一个hello world级别的main.cpp编译都要分几步的情况(有时候还有问题), 所以这也算是一大进步 - 现在可以像下面一样一键编译 <code>import std</code> 的程序了</p>
<pre><code class="language-cpp">// main.cpp
import std;

int main() {
    std::println("{}", 42);
}
</code></pre>
<p dir="auto">编译:</p>
<pre><code class="language-bash">g++ -std=c++23 -fmodules --compile-std-module main.cpp -o app
./app
</code></pre>
<h2>3. 诊断增强: 错误信息结构化 + 编译期静态代码分析</h2>
<p dir="auto">C++ 报错经常被吐槽，不是因为编译器不知道哪里错了，而是因为错误链太长，人很难从一堆候选函数、模板实例化和类型展开里看出主线。</p>
<p dir="auto">GCC 16 的一个明显变化是，部分 C++ 错误信息开始用层级结构展示。例如这个声明和定义不一致的例子:</p>
<pre><code class="language-cpp">class Foo {
public:
    void test(int i, int j, void *ptr, int k);
};

void Foo::test(int i, int j, const void *ptr, int k) {
}

int main() {
    return 0;
}
</code></pre>
<p dir="auto">编译:</p>
<pre><code class="language-bash">g++ diagnostics-mismatch.cpp
</code></pre>
<p dir="auto">GCC 16 会把候选函数和参数差异分层展示，核心信息大致是:</p>
<pre><code class="language-text">error: no declaration matches 'void Foo::test(int, int, const void*, int)'
  - there is 1 candidate
    - candidate is: 'void Foo::test(int, int, void*, int)'
      - parameter 3 of candidate has type 'void*'
      - which does not match type 'const void*'
</code></pre>
<p dir="auto">这比以前只告诉你 找不到匹配声明 更有用，它一定程度指出了候选是谁、哪里不一致、哪一个参数出了问题。</p>
<p dir="auto">甚至还能生成更适合浏览器查看的诊断html页面:</p>
<pre><code class="language-bash">g++ diagnostics-mismatch.cpp \
  -fdiagnostics-add-output=experimental-html
</code></pre>
<p dir="auto"><img src="/assets/uploads/files/1777910315147-2026-05-04_22-55.png" alt="2026-05-04_22-55.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">如果想给 CI、IDE 或代码扫描平台使用，可以生成 SARIF:</p>
<pre><code class="language-bash">g++ diagnostics-mismatch.cpp \
  -fdiagnostics-format=sarif 
</code></pre>
<p dir="auto">这个的优化, 不仅 报错更容易看了，而且后面可能会影响工具链体验。编译器不再只是把错误打印到终端，而是可以把结构化诊断交给网页、编辑器、代码审查和静态分析系统。</p>
<p dir="auto">配合上 <code>-fanalyzer</code> 的能力。它是 GCC 自带的静态分析能力。如果加上 <code>-Werror</code> 体验就有点类似Rust的严格编译期检查功能</p>
<p dir="auto">看一个 use-after-delete:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

int main() {
    int *p = new int(42);
    delete p;
    std::cout &lt;&lt; *p &lt;&lt; "\n";
}
</code></pre>
<p dir="auto">编译:</p>
<pre><code class="language-bash">g++ -std=c++20 -fanalyzer analyzer-uaf.cpp
</code></pre>
<p dir="auto">GCC 16 会给出类似警告:</p>
<pre><code class="language-text">warning: use after 'delete' of 'p' [CWE-416] [-Wanalyzer-use-after-free]
</code></pre>
<p dir="auto"><img src="/assets/uploads/files/1777910360646-6ac11e44-be1d-4668-bd20-b4243eb62f81-image.png" alt="6ac11e44-be1d-4668-bd20-b4243eb62f81-image.png" class=" img-fluid img-markdown" /></p>
<h2>4. C++26 特性: Reflection / 反射</h2>
<p dir="auto">GCC 16 实现了若干 C++26 特性，这里简单试一试</p>
<pre><code class="language-bash">-std=c++26 -freflection
</code></pre>
<p dir="auto">以一个简单的结构体为例, 看看 C++26反射 的功能:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;meta&gt;
#include &lt;string_view&gt;

struct User {
    int id;
    double score;
};

consteval std::size_t field_count() {
    auto fields = std::meta::nonstatic_data_members_of(
        ^^User,
        std::meta::access_context::unchecked()
    );
    return fields.size();
}

consteval std::string_view field_name(std::size_t index) {
    auto fields = std::meta::nonstatic_data_members_of(
        ^^User,
        std::meta::access_context::unchecked()
    );
    return std::meta::identifier_of(fields[index]);
}

consteval std::string_view field_type(std::size_t index) {
    auto fields = std::meta::nonstatic_data_members_of(
        ^^User,
        std::meta::access_context::unchecked()
    );
    return std::meta::display_string_of(std::meta::type_of(fields[index]));
}

int main() {
    constexpr auto type_name = std::meta::display_string_of(^^User);

    std::cout &lt;&lt; type_name &lt;&lt; " has " &lt;&lt; field_count() &lt;&lt; " fields\n";
    std::cout &lt;&lt; field_name(0) &lt;&lt; ": " &lt;&lt; field_type(0) &lt;&lt; '\n';
    std::cout &lt;&lt; field_name(1) &lt;&lt; ": " &lt;&lt; field_type(1) &lt;&lt; '\n';
}
</code></pre>
<p dir="auto">编译运行:</p>
<pre><code class="language-bash">g++ -std=c++26 -freflection reflection-user.cpp -o reflection-user
./reflection-user
</code></pre>
<p dir="auto">输出:</p>
<pre><code class="language-text">User has 2 fields
id: int
score: double
</code></pre>
<p dir="auto">这里的 <code>^^User</code> 是对 <code>User</code> 这个结构体类型做静态反射，<code>std::meta::display_string_of</code> 可以拿到类型的显示名。<code>std::meta::nonstatic_data_members_of</code> 则能拿到结构体的非静态数据成员列表，再通过 <code>identifier_of</code> 和 <code>type_of</code> 分别取得成员名和成员类型。</p>
<p dir="auto">C++ 代码可以在编译期拿到结构体自身的字段信息。这个功能对 序列化、ORM、RPC、命令行参数解析、UI 绑定、测试生成等大量现在依赖宏、模板技巧或外部代码生成的场景 有重要影响</p>
<h2>5. 总结</h2>
<p dir="auto">GCC 16.1.0 感觉最核心的就是默认标准从C++17变成了C++20, 某种意义上也算正式迈入C++2x时代了, 下面是一些个人感觉</p>
<ul>
<li>1.默认 C++ 标准从 GNU++17 变成 GNU++20。能进一步加速C++生态进入C++2x的时代</li>
<li>2.C++20 modules特性 在 GCC 16 里只是做了部分优化, 相比GCC 15.1.0引入import std来说, 没有特别惊喜</li>
<li>3.诊断输出更结构化了。嵌套错误、HTML、SARIF 会让编译器错误更适合教学、CI 和 IDE 集成。</li>
<li>4.C++26 Reflection 已经可以初步尝试。对于个人项目可以上手用一用 (但可能存在很多潜在的坑)</li>
</ul>
<p dir="auto">我个人是比较关注模块化的进展, 总体来说GCC16虽然模块化特性上没有过多惊喜, 但在<code>import std</code>之后, 模块化算是已经初步可以在项目里尝试的水平了, 并且我们 mcpp-community 现代C++爱好者社区 已经在 模块化的 项目/库的 工程化、包管理、工具链 等方面有一定的探索, 欢迎感兴趣的朋友加入讨论</p>
<ul>
<li>社区Github主页: <a href="https://github.com/mcpp-community" rel="nofollow ugc">https://github.com/mcpp-community</a></li>
<li>C++23模块化项目: <a href="https://github.com/openxlings/xlings" rel="nofollow ugc">https://github.com/openxlings/xlings</a></li>
<li>C++23模块化库: <a href="https://github.com/mcpplibs" rel="nofollow ugc">https://github.com/mcpplibs</a></li>
</ul>
<h2>相关链接</h2>
<ul>
<li>xlings: <a href="https://github.com/openxlings/xlings" rel="nofollow ugc">https://github.com/openxlings/xlings</a></li>
<li>mcpp-community: <a href="https://github.com/mcpp-community" rel="nofollow ugc">https://github.com/mcpp-community</a></li>
<li>GCC 16.1 Released: <a href="https://gcc.gnu.org/pipermail/gcc-announce/2026/000190.html" rel="nofollow ugc">https://gcc.gnu.org/pipermail/gcc-announce/2026/000190.html</a></li>
<li>GCC 16 Release Series: Changes, New Features, and Fixes: <a href="https://gcc.gnu.org/gcc-16/changes.html" rel="nofollow ugc">https://gcc.gnu.org/gcc-16/changes.html</a></li>
<li>GCC 16.1.0: <a href="https://sourceware.org/pub/gcc/releases/gcc-16.1.0/" rel="nofollow ugc">https://sourceware.org/pub/gcc/releases/gcc-16.1.0/</a></li>
</ul>
]]></description><link>http://forum.d2learn.org/topic/203/gcc-16-上手初体验-环境配置-默认-c-20-模块化-诊断增强和-c-26-反射</link><guid isPermaLink="true">http://forum.d2learn.org/topic/203/gcc-16-上手初体验-环境配置-默认-c-20-模块化-诊断增强和-c-26-反射</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[请教如何自定义异常]]></title><description><![CDATA[class myException : public std::exception {
private:
    std::string _msg;
public:
    myException(const char* message) noexcept : _msg(message) {}
    
    const char* what() const noexcept override {
        return _msg.c_str();
    }
};

]]></description><link>http://forum.d2learn.org/topic/182/请教如何自定义异常</link><guid isPermaLink="true">http://forum.d2learn.org/topic/182/请教如何自定义异常</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[使用自编C++Web框架搭建的个人博客]]></title><description><![CDATA[<p dir="auto">@unamed-coder 看https://glwebsite.us.ci/about下边的小字，我真不是福瑞</p>
]]></description><link>http://forum.d2learn.org/topic/173/使用自编c-web框架搭建的个人博客</link><guid isPermaLink="true">http://forum.d2learn.org/topic/173/使用自编c-web框架搭建的个人博客</guid><dc:creator><![CDATA[MineCode]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[在CLion 2025.3.2中配置xmake项目]]></title><description><![CDATA[<p dir="auto">@SPeak 具体没研究过，不过JetBrains的IDE集成程度比vscode高，可能不太能通过命令或者修改配置文件的方式来修改。如果有朋友有相关了解的可以贴在这里。</p>
]]></description><link>http://forum.d2learn.org/topic/168/在clion-2025-3-2中配置xmake项目</link><guid isPermaLink="true">http://forum.d2learn.org/topic/168/在clion-2025-3-2中配置xmake项目</guid><dc:creator><![CDATA[FrozenLemonTee]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[mcpp在远程连接ubuntu的vscode中使用d2x checker命令，编辑器无法识别代码]]></title><description><![CDATA[<p dir="auto">@sunrisepeak 解决了👍</p>
]]></description><link>http://forum.d2learn.org/topic/166/mcpp在远程连接ubuntu的vscode中使用d2x-checker命令-编辑器无法识别代码</link><guid isPermaLink="true">http://forum.d2learn.org/topic/166/mcpp在远程连接ubuntu的vscode中使用d2x-checker命令-编辑器无法识别代码</guid><dc:creator><![CDATA[fillSea]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[讨论: 现代C++编码&#x2F;项目风格]]></title><description><![CDATA[<p dir="auto">目前社区准备制作一份 现代C++ (特别是模块化) 相关的编码和项目组织结构方面的风格参考项目, 例如 模块和头文件兼容、命名风格、接口导出、以及常用技巧的"最佳"实践等.....</p>
<p dir="auto"><strong>欢迎大家在这里交流、讨论、反馈</strong></p>
<ul>
<li><a href="https://github.com/mcpp-community/mcpp-style-ref" rel="nofollow ugc">https://github.com/mcpp-community/mcpp-style-ref</a></li>
</ul>
<p dir="auto"><img src="/assets/uploads/files/1770186717105-0fc7c94b-4e00-4c33-ba5b-65d7967597fc-image.png" alt="0fc7c94b-4e00-4c33-ba5b-65d7967597fc-image.png" class=" img-fluid img-markdown" /></p>
]]></description><link>http://forum.d2learn.org/topic/163/讨论-现代c-编码-项目风格</link><guid isPermaLink="true">http://forum.d2learn.org/topic/163/讨论-现代c-编码-项目风格</guid><dc:creator><![CDATA[sunrisepeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[终端使用xlings checker不显示代码 - 自动打开的是空文件以及检测没有实时更新]]></title><description><![CDATA[<p dir="auto">补充: 检测终端没有实时更新问题解决方法</p>

方法1: 修改代码后手动(ctrl + s)保存文件, 检测程序即可自动检测到
方法2: 设置vscode自动保

<p dir="auto">image.png</p>
]]></description><link>http://forum.d2learn.org/topic/142/终端使用xlings-checker不显示代码-自动打开的是空文件以及检测没有实时更新</link><guid isPermaLink="true">http://forum.d2learn.org/topic/142/终端使用xlings-checker不显示代码-自动打开的是空文件以及检测没有实时更新</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[活动 | MSCP | mcpp项目学习与贡献者培养计划]]></title><description><![CDATA[<p dir="auto">MSCP是一款基于<a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard</a>开源项目开发的"地球Online"风格的角色扮演游戏。在游戏中你将扮演一个"编程初学者", 为了入门"现代C++"并揭露其背后的真相, 踏上了一条充满挑战和惊奇的现代C++学习之路...</p>
<ul>
<li><code>价格:</code> 免费</li>
<li><code>开发者:</code> <a href="https://github.com/Sunrisepeak" rel="nofollow ugc">Sunrisepeak</a></li>
<li><code>发行商:</code> <a href="https://d2learn.github.io/MOGA/" rel="nofollow ugc">MOGA</a></li>
<li><code>发行时间:</code> 预计2025年10月</li>
<li><code>游戏体量:</code> 100H - 200H之间</li>
<li><code>标签:</code> 类魂系列、模拟人生、<img src="http://forum.d2learn.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f30d.png?v=c6uec18e3vu" class="not-responsive emoji emoji-android emoji--earth_africa" style="height:23px;width:auto;vertical-align:middle" title=":earth_africa:" alt="🌍" />Online、程序员、C++、开源、费曼学习法</li>
</ul>
<h2>mcpp-standard开源项目简介</h2>
<p dir="auto">一个 <code>强调动手实践</code> 的 <code>现代C++</code> 入门教程项目。以现代C++的核心语言特性为基础, 开发了一套 [Book + Video + Code + X] 结构的"现代"教程。其中:</p>
<ul>
<li><code>Book:</code> 对应的是提供在线电子书和文档解析</li>
<li><code>Video:</code> 提供核心语言特性的讲解视频</li>
<li><code>Code:</code> 提供对应的代码练习及自动化检测工具(包括在线代码练习环境)</li>
<li><code>X:</code> 提供项目的社区论坛和交流讨论群组</li>
</ul>
<p dir="auto">项目的电子书、练习代码及相关工具开源在Github上, 视频发布在Bilibili和Youtube上</p>
<ul>
<li>项目开源地址: <a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">https://github.com/Sunrisepeak/mcpp-standard</a></li>
<li>项目视频列表: <a href="https://www.bilibili.com/video/BV182MtzPEiX" rel="nofollow ugc">bilibili</a> / <a href="https://youtu.be/q4TPrcrhEjg?si=qKZaALCHAxM2OcJ-" rel="nofollow ugc">youtube</a></li>
</ul>
<p dir="auto"><a href="https://www.star-history.com/#Sunrisepeak/mcpp-standard&amp;Date" rel="nofollow ugc"><img src="https://api.star-history.com/svg?repos=Sunrisepeak/mcpp-standard&amp;type=Date" alt="Star History Chart" class=" img-fluid img-markdown" /></a></p>
<p dir="auto">项目之前也被业内媒体 <a href="https://hellogithub.com/repository/Sunrisepeak/mcpp-standard" rel="nofollow ugc">HelloGithub</a> 收录和分享过(112期)</p>
<p dir="auto"><a href="https://hellogithub.com/repository/Sunrisepeak/mcpp-standard" rel="nofollow ugc"><img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=7877f7cb12e940a5a432d49c19a360df&amp;claim_uid=aNLTSv91Awj8ruX&amp;theme=dark" alt="" class=" img-fluid img-markdown" /></a></p>
<h2>一、活动内容</h2>
<p dir="auto">活动以<a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard</a>项目现有的<code>核心语言特性</code>的学习和<code>交互式的代码练习</code>的完成为 <a href="https://moga.d2learn.org/activity/mscp/docs/flowchart-details.html#%E4%B8%80%E3%80%81%E4%B8%BB%E7%BA%BF%E6%B4%BB%E5%8A%A8" rel="nofollow ugc">主线剧情</a> , 并在过程中 玩家先扮演C++学习者, 学习相关的核心特性, 然后再扮演技术分享者 把学到的C++特性用自己的语言和逻辑在分享给其他人, <code>双重视角 + 费曼学习法</code>来快速入门现代C++</p>
<p dir="auto">同时活动也设置了 <a href="https://moga.d2learn.org//activity/mscp/docs/flowchart-details.html#%E4%BA%8C%E3%80%81%E6%94%AF%E7%BA%BF%E6%B4%BB%E5%8A%A8" rel="nofollow ugc">支线剧情</a> 的玩法, 玩家在完成新手村任务(T0)后, 即可选择申请加入 <a href="https://moga.d2learn.org//activity/mscp/docs/join-group.html" rel="nofollow ugc">活动小组</a>, 然后就可以以团队协作的方式, 参与活动/社区/项目的开发和维护中, 感受一个开源项目和社区是如何运行的...</p>
<h3>目标</h3>
<ul>
<li>基础目标
<ul>
<li>初步的入门/了解现代C++</li>
<li>使用<a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard</a>和<a href="https://cppreference.com" rel="nofollow ugc">cppreference</a>持续学习的能力</li>
<li>具备成为现代C++的技术分享者/布道者的初步能力(编写技术文章、制作教学视频...</li>
<li>成为<a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard</a>项目的贡献者(至少合入一次PR</li>
</ul>
</li>
<li>扩展目标(可选
<ul>
<li>了解活动/开源项目和社区的开发和运营方法</li>
<li>参与活动/项目/社区的维护和开发</li>
<li>成为<a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard</a>项目和社区的核心贡献者/开发者</li>
</ul>
</li>
</ul>
<h3>流程结构和玩法</h3>
<blockquote>
<p dir="auto">活动整体设计了主线剧情 + 可选的支线剧情</p>
<ul>
<li>核心玩法/主线: <code>[学习现代C++核心特性 -&gt; 把学到教会其他人 -&gt; 参与社区讨论]</code> 循环这个过程</li>
</ul>
</blockquote>
<p dir="auto"><img src="https://moga.d2learn.org/imgs/activity/mscp-flowchart.svg" alt="" class=" img-fluid img-markdown" /></p>
<ul>
<li>活动的任务发布和活动基于<a href="https://github.com/orgs/d2learn/projects/6" rel="nofollow ugc">Github项目看板</a>进行管理和记录</li>
<li>虚线箭头表示可选路径, 详细介绍参考 -&gt; <a href="https://moga.d2learn.org/activity/mscp/docs/flowchart-details.html" rel="nofollow ugc">MSCP | 流程结构详细介绍</a></li>
</ul>
<h2>二、如何参与和游玩 ?</h2>
<blockquote>
<p dir="auto">由于活动涉及的项目/材料/工具内容, 几乎都是开源的, 所以理论任何人都可以参与该活动</p>
</blockquote>
<ul>
<li><a href="https://moga.d2learn.org/activity/mscp/docs/start.html" rel="nofollow ugc">从完成第一个任务开始</a></li>
<li><a href="https://moga.d2learn.org/activity/mscp/docs/join-group.html" rel="nofollow ugc">加入活动小组(可选)</a></li>
</ul>
<p dir="auto">::: tip</p>
<p dir="auto">如果参与中遇到问题/困难, 可以 查看 <a href="https://moga.d2learn.org/activity/mscp/qa.html" rel="nofollow ugc">常见问题</a> 或 在论坛创建话题贴 -&gt; <a href="https://forum.d2learn.org/category/20" rel="nofollow ugc">mcpp论坛</a></p>
<blockquote>
<p dir="auto">注: 活动相关的文档/工具等资源可以查看 -&gt; <a href="https://moga.d2learn.org/activity/mscp/docs/map.html" rel="nofollow ugc">活动地图</a></p>
</blockquote>
<p dir="auto">:::</p>
<h2>三、社区</h2>
<ul>
<li><a href="https://forum.d2learn.org/category/20" rel="nofollow ugc">mcpp论坛</a></li>
<li><a href="https://github.com/orgs/d2learn/projects/6" rel="nofollow ugc">活动工作流看板</a></li>
<li>mcpp活动交流群: 1067245099</li>
<li>MOGA交流群(可选): 1065632930</li>
</ul>
<h2>四、相关链接</h2>
<ul>
<li><a href="https://moga.d2learn.org/activity/mscp/docs/map.html" rel="nofollow ugc">活动地图</a></li>
<li><a href="https://moga.d2learn.org/activity/mscp/qa.html" rel="nofollow ugc">常见问题</a></li>
<li><a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">mcpp-standard项目开源仓库</a></li>
<li><a href="https://github.com/orgs/d2learn/projects/6" rel="nofollow ugc">活动工作流看板</a></li>
<li><a href="https://moga.d2learn.org/activity/mscp/log.html" rel="nofollow ugc">活动记录</a></li>
</ul>
]]></description><link>http://forum.d2learn.org/topic/140/活动-mscp-mcpp项目学习与贡献者培养计划</link><guid isPermaLink="true">http://forum.d2learn.org/topic/140/活动-mscp-mcpp项目学习与贡献者培养计划</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[devcpp光标位置和显示乱码问题: 调完字体大小后光标位置不对啊，有没有大佬看看(用xlings下的文字也有问题）]]></title><description><![CDATA[<p dir="auto">@SPeak 在 调完字体大小后光标位置不对啊，有没有大佬看看(用xlings下的文字也有问题） 中说：</p>
<blockquote>
<p dir="auto">http://forum.d2learn.org/post/418</p>
</blockquote>
<p dir="auto">问题1: 界面乱码问题</p>
<blockquote>
<p dir="auto">A1: xlings已经更新解决(增加了utf8编码的支持, 重装即可</p>
</blockquote>
<p dir="auto">问题2: 代码输入光标位置问题</p>
<blockquote>
<p dir="auto">解决方法1: 代码中不要包含中文内容<br />
解决方法2: 取消beta/utf8编码选项, 然后卸载重新安装devcpp</p>
</blockquote>
xlings remove devcpp
xlings install devcpp

<p dir="auto">6c34d5cd-b1eb-4c7f-8181-1ca3ca6c673b-image.png</p>

<p dir="auto">中/英文切换: https://forum.d2learn.org/topic/134</p>
]]></description><link>http://forum.d2learn.org/topic/137/devcpp光标位置和显示乱码问题-调完字体大小后光标位置不对啊-有没有大佬看看-用xlings下的文字也有问题</link><guid isPermaLink="true">http://forum.d2learn.org/topic/137/devcpp光标位置和显示乱码问题-调完字体大小后光标位置不对啊-有没有大佬看看-用xlings下的文字也有问题</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[关于c++17结构化绑定的一些问题 - auto&amp; [u_2, v_2] 结构化绑定, 为什么decltype(u_2)结果是int而不是int&amp;呢]]></title><description><![CDATA[<p dir="auto">这里decltype 对结构化绑定的别名有个特殊处理 返回的 <strong>引用类型</strong> 是结构化绑定中特殊定义的, 不是传统认为的 引用类型, 指的是成员的声明类型, 除非成员是 T &amp; 才会返回 T &amp;</p>
<p dir="auto">image.png</p>

https://en.cppreference.com/w/cpp/language/decltype.html

<p dir="auto">image.png</p>

https://en.cppreference.com/w/cpp/language/structured_binding.html

]]></description><link>http://forum.d2learn.org/topic/136/关于c-17结构化绑定的一些问题-auto-u_2-v_2-结构化绑定-为什么decltype-u_2-结果是int而不是int-呢</link><guid isPermaLink="true">http://forum.d2learn.org/topic/136/关于c-17结构化绑定的一些问题-auto-u_2-v_2-结构化绑定-为什么decltype-u_2-结果是int而不是int-呢</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[【xlings】一键安装配置Dev C++以及中&#x2F;英文设置的三种方法, 镜像下载加速]]></title><description><![CDATA[<p dir="auto">@335582 可能是编码问题: http://forum.d2learn.org/post/597</p>
]]></description><link>http://forum.d2learn.org/topic/134/xlings-一键安装配置dev-c-以及中-英文设置的三种方法-镜像下载加速</link><guid isPermaLink="true">http://forum.d2learn.org/topic/134/xlings-一键安装配置dev-c-以及中-英文设置的三种方法-镜像下载加速</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[json库的initializer_list创建问题]]></title><description><![CDATA[<p dir="auto">@SPeak<br />
按照这个思路，只保留一个列表初始化，用了一个辅助函数检测了每个元素是否是数组，如果是数组就检测长度是否是2，然后首元素是否是string，如果初始化列表里全部元素都符合就判定为object。这个代码运行成功了，感谢大佬</p>
  Json(std::initializer_list&lt;Json&gt; init) {
    if (is_object_list(init)) {
      JsonObject dict;
      for (const auto &amp;el : init) {
        auto pair = std::get_if&lt;JsonArray&gt;(&amp;el.m_value);
        // 必须是长度为2的数组
        assert(pair &amp;&amp; pair-&gt;size() == 2);
        auto key = std::get_if&lt;std::string&gt;(&amp;(*pair)[0].m_value);
        // 第一个元素必须是字符串
        assert(key);
        dict.emplace(*key, (*pair)[1]);
      }
      m_value = std::move(dict);
    } else {
      m_value = JsonArray(init);
    }
  }

  bool is_object_list(std::initializer_list&lt;Json&gt; init) {
    return std::all_of(init.begin(), init.end(), [](const Json &amp;el) {
      auto pair = std::get_if&lt;JsonArray&gt;(&amp;el.m_value);
      if (!pair || pair-&gt;size() != 2)
        return false;
      return std::holds_alternative&lt;std::string&gt;((*pair)[0].m_value);
    });
  }

]]></description><link>http://forum.d2learn.org/topic/131/json库的initializer_list创建问题</link><guid isPermaLink="true">http://forum.d2learn.org/topic/131/json库的initializer_list创建问题</guid><dc:creator><![CDATA[dustchens]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[关于sonic实现音频变速不变调的问题]]></title><description><![CDATA[<p dir="auto">hi,友友有解决这个情况吗，我也是当speed不为一时就报错了，我完全不知道如何查找崩溃，找了一天了，下面是我的代码：<br />
void AudioDecodeThread::run()<br />
{<br />
// 加入sonic<br />
// 初始化部分：先创建一个流<br />
sonicStream stream = sonicCreateStream(m_videoPlayControl-&gt;m_audioCodecCtx-&gt;sample_rate, 2);<br />
if (!stream)<br />
{<br />
m_videoPlayControl-&gt;m_eventHandler-&gt;onVideoPlayerError(0, "sonicCreateStream error!");<br />
}</p>
    if (!initSwrCtx())
    {
        m_videoPlayControl-&gt;m_eventHandler-&gt;onVideoPlayerError(0, "initSwrCtx error");
        return;
    }

    while (true)
    {
        if (m_videoPlayControl-&gt;m_currentState == State::STOP)
        {
            break;
        }
        else if (m_videoPlayControl-&gt;m_currentState == State::PAUSE)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            continue;
        }

        AVPacket *pkt = m_videoPlayControl-&gt;m_audioPacketQueue.pop();
        if (pkt == nullptr)
        {
            if (m_videoPlayControl-&gt;m_isReadFinished)
            {
                break;
            }
            continue;
        }

        if (memcmp(pkt-&gt;data, FLUSHDATA, strlen(FLUSHDATA)) == 0)
        {
            avcodec_flush_buffers(m_videoPlayControl-&gt;m_audioCodecCtx);
            av_packet_free(&amp;pkt);
            continue;
        }

        int ret = avcodec_send_packet(m_videoPlayControl-&gt;m_audioCodecCtx, pkt);
        if (ret &lt; 0)
        {
            char errbuf[1024] = { 0 };
            av_strerror(ret, errbuf, sizeof(errbuf));
            fprintf(stderr, "avcodec_send_packet: %s (error pts: %d)\n", errbuf, pkt-&gt;pts);
            av_packet_free(&amp;pkt);
            continue;
        }

        AVFrame *frame = av_frame_alloc();
        while (avcodec_receive_frame(m_videoPlayControl-&gt;m_audioCodecCtx, frame) == 0)
        {
            // 读取frame, swr转换, 放到frameQueue里面去
            int inSamples = frame-&gt;nb_samples;
            // int outSamples = av_rescale_rnd(inSamples, 1, 1, AV_ROUND_UP);

            // 废除手动分配的 audioBuffer，改用 resampleFrame 内部缓冲区
            AVFrame *resampleFrame = av_frame_alloc();
            resampleFrame-&gt;format = AV_SAMPLE_FMT_S16;
            av_channel_layout_default(&amp;resampleFrame-&gt;ch_layout, 2); // 双声道
            resampleFrame-&gt;sample_rate = frame-&gt;sample_rate;         // 正确设置采样率
            resampleFrame-&gt;nb_samples = inSamples;

            // 让 FFmpeg 自动分配缓冲区（确保地址和大小正确）
            if (av_frame_get_buffer(resampleFrame, 0) &lt; 0)
            {
                av_frame_free(&amp;resampleFrame);
                continue;
            }

            int len = swr_convert(m_swrCtx, resampleFrame-&gt;data, resampleFrame-&gt;nb_samples, (const uint8_t **)frame-&gt;data, inSamples);

            // 加入sonic

            sonicSetSpeed(stream, m_videoPlayControl-&gt;m_speed);
            // 4. 写入音频数据到Sonic ,这里的bug

            short *valid_audio_data = (short *)resampleFrame-&gt;data[0];
            int total_samples = len; // 单声道总样本数

            std::cout &lt;&lt; len &lt;&lt; std::endl;

            ret = sonicWriteShortToStream(stream, valid_audio_data, total_samples);
            if (ret == 0)
            {
                m_videoPlayControl-&gt;m_eventHandler-&gt;onVideoPlayerError(0, "sonicWriteShortToStream error");
                continue;
            }

            int availableSamples = sonicSamplesAvailable(stream); //
            if (availableSamples &lt;= 0)
            {
                continue;
            }

            // 根据实际需要的样本数分配缓冲区
            short *output_pcm = new short[availableSamples * 2];
            int samples = sonicReadShortFromStream(stream, output_pcm, availableSamples);
            if (samples &lt;= 0)
            {
                delete[] output_pcm;
                av_frame_free(&amp;resampleFrame);
                continue;
            }

            std::cout &lt;&lt; inSamples &lt;&lt; "---" &lt;&lt; len &lt;&lt; "---" &lt;&lt; availableSamples &lt;&lt; "---" &lt;&lt; samples &lt;&lt; std::endl;

            PCMFrame *pcm = new PCMFrame();
            pcm-&gt;setBuffer((uint8_t *)output_pcm, samples * 4);
            pcm-&gt;setPts(frame-&gt;pts);
            pcm-&gt;setSampleRate(frame-&gt;sample_rate);
            m_videoPlayControl-&gt;m_audioFrameQueue.push(pcm);

            delete[] output_pcm;
            av_frame_free(&amp;resampleFrame);
        }
        av_frame_free(&amp;frame);
        av_packet_free(&amp;pkt);
    }
    sonicDestroyStream(stream);
}

]]></description><link>http://forum.d2learn.org/topic/122/关于sonic实现音频变速不变调的问题</link><guid isPermaLink="true">http://forum.d2learn.org/topic/122/关于sonic实现音频变速不变调的问题</guid><dc:creator><![CDATA[Cat-Guijun]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[[项目更新 | 2025&#x2F;7&#x2F;21]: 增加了同步最新练习代码的功能]]></title><description><![CDATA[<p dir="auto">由于项目处于持续更新阶段, 可以使用下面的命令进行自动同步(如果同步失败, 可能需要手动用git进行更新项目代码)</p>
<pre><code class="language-bash">d2x update
</code></pre>
<p dir="auto"><img src="/assets/uploads/files/1753072760122-10f89f6b-cc49-4636-ae4f-308e77f22c36-image.png" alt="10f89f6b-cc49-4636-ae4f-308e77f22c36-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto"><img src="/assets/uploads/files/1753072720565-3b0ab32f-4418-47cc-9525-fd793dfcdf39-image.png" alt="3b0ab32f-4418-47cc-9525-fd793dfcdf39-image.png" class=" img-fluid img-markdown" /></p>
<hr />
<p dir="auto">PR: <a href="https://github.com/Sunrisepeak/mcpp-standard/pull/8" rel="nofollow ugc">https://github.com/Sunrisepeak/mcpp-standard/pull/8</a></p>
<blockquote>
<p dir="auto">注: 需要更新到最新版本的xlings</p>
</blockquote>
]]></description><link>http://forum.d2learn.org/topic/116/项目更新-2025-7-21-增加了同步最新练习代码的功能</link><guid isPermaLink="true">http://forum.d2learn.org/topic/116/项目更新-2025-7-21-增加了同步最新练习代码的功能</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[win环境下执行xlings checker 会报错为：error: wait events in poller failed! 当编写 vscode的时候会显示无法写入使得崩溃]]></title><description><![CDATA[<p dir="auto">@Saaqq 目前d2x工具使用c++重构了, 可以更新一下 应该不会有这个问题了</p>
<p dir="auto">先更新一下d2x工具</p>
xlings self update
xim --update index
xlings update d2x

<p dir="auto">然后再到项目目录运行下面命令进入练习模式</p>
d2x checker

<blockquote>
<p dir="auto">注: 最新版本的d2x也支持配置AI大模型做智能引导, 也可以玩一玩</p>
</blockquote>
<p dir="auto">33e4df78-8646-4b89-847f-41899668b251-image.png</p>

移植后的d2x仓库: https://github.com/d2learn/d2x
交互式教程说明: https://d2learn.github.io/d2x-project-template/chapter_0.html

]]></description><link>http://forum.d2learn.org/topic/114/win环境下执行xlings-checker-会报错为-error-wait-events-in-poller-failed-当编写-vscode的时候会显示无法写入使得崩溃</link><guid isPermaLink="true">http://forum.d2learn.org/topic/114/win环境下执行xlings-checker-会报错为-error-wait-events-in-poller-failed-当编写-vscode的时候会显示无法写入使得崩溃</guid><dc:creator><![CDATA[sunrisepeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[离散数学-0x00]]></title><description><![CDATA[<p dir="auto">本系列博客作为我学习的一个笔记,注重于代码实现,本人非数学专业,证明能力非常弱,本文掺杂着大量我自己的理解,如有数学大佬光顾,请尽情指正,谢谢<br />
<strong>本系列默认大家都学会了C/C++基本语法</strong></p>
<h1>集合</h1>
<h2>书上的定义</h2>
<pre><code>集合是指具有某种特定性质的不同对象无序聚集成的一个整体。
集合中的每一个对象称为集合的元素；
通常用大写字母表示集合；
用小写字母表示集合中的元素。
</code></pre>
<p dir="auto">也就是说把一些东西放到一起叫做集合(个人理解)</p>
<h3>代码实现</h3>
<pre><code>#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;stdint.h&gt;
#include &lt;iostream&gt;

// 抽象基类，定义集合元素的基本接口
class elmBase
{
public:
    // 将元素转换为字节数组的纯虚函数（序列化基础）
    virtual std::vector&lt;uint8_t&gt; getUint8Array() const = 0;

    // 默认比较运算符，通过字节数组逐字节比较
    virtual int operator==(const elmBase &amp;other)
    {
        std::vector&lt;uint8_t&gt; thisDate = getUint8Array();
        std::vector&lt;uint8_t&gt; otherDate = other.getUint8Array();
        if (thisDate.size() != otherDate.size())
            return 0;
        for (int i = 0; i &lt; thisDate.size(); i++)
        {
            if (thisDate[i] != otherDate[i])
                return 0;
        }
        return 1;
    }

    // 转换为字符串表示的纯虚函数
    virtual std::string toString() = 0;

    // 虚析构函数确保正确释放派生类对象
    virtual ~elmBase()
    {
    }
};

// 特殊元素类型，始终返回比较不成立
class alwaysFalse : public elmBase
{
public:
    std::vector&lt;uint8_t&gt; getUint8Array() const override
    {
        return std::vector&lt;uint8_t&gt;(); // 返回空数组
    }

    std::string toString() override
    {
        return {}; // 返回空字符串
    }

    // 重载运算符始终返回false，用于占位符场景
    virtual int operator==(const elmBase &amp;other) override
    {
        return 0;
    }
    ~alwaysFalse()
    {
    }
};

// 哈希表节点结构，使用链表法解决冲突
using elmNode = struct elmNode
{
    elmBase *elm;  // 元素指针
    elmNode *next; // 下一个节点指针
};

// 节点工厂函数，创建新节点并初始化元素
elmNode *elmNodeFactory(elmBase *elm)
{
    elmNode *newNode = new elmNode();
    newNode-&gt;elm = elm;
    newNode-&gt;next = nullptr;
    return newNode;
}

// 自定义集合类，基于哈希表实现
class set
{
private:
    uint32_t prime;   // 哈希表大小（通常选择质数）
    elmNode **setMap; // 哈希桶数组

    // 初始化哈希表结构
    void inline _init_(uint32_t prime)
    {
        this-&gt;prime = prime;
        this-&gt;setMap = new elmNode *[prime];
        // 初始化每个桶为alwaysFalse哨兵节点
        for (uint32_t i = 0; i &lt; prime; ++i)
        {
            this-&gt;setMap[i] = elmNodeFactory(new alwaysFalse());
        }
    }

protected:
    // 查找元素对应的哈希桶
    elmNode **__find__(elmBase *elm)
    {
        uint32_t hash = rotatingHash(elm-&gt;getUint8Array(), this-&gt;prime);
        return &amp;(this-&gt;setMap[hash]); // 返回桶的指针
    }

    /**
     * 通用链表操作函数
     * @param link 链表头指针的指针
     * @param elm 目标元素
     * @param cmp 自定义比较函数，返回true时停止遍历
     * @param finally 遍历结束后的处理函数（插入等操作）
     * @return 找到的节点或操作结果节点
     */
    elmNode *__link__(elmNode **link, elmBase *elm,
                      bool (*cmp)(elmNode *, elmBase *),
                      elmNode *(*finally)(elmNode **, elmNode *, elmBase *) = nullptr)
    {
        elmNode *linkPriv = *link;
        elmNode *linkCurrent = linkPriv;

        // 遍历链表查找元素
        while (linkCurrent != nullptr)
        {
            if (cmp(linkCurrent, elm))
            {
                return linkCurrent;
            }
            linkPriv = linkCurrent;
            linkCurrent = linkCurrent-&gt;next;
        }

        // 执行最终处理函数（如插入新节点）
        if (finally != nullptr)
        {
            return finally(link, linkPriv, elm);
        }
        return nullptr;
    }

public:
    // 构造函数初始化哈希表
    set(uint32_t prime) { _init_(prime); }
    ~set()
    {
        for (uint32_t i = 0; i &lt; this-&gt;prime; ++i)
        {
            elmNode *link = this-&gt;setMap[i];
            while (link != nullptr)
            {
                elmNode *tmp = link;
                link = link-&gt;next;
                if (tmp != nullptr)
                {
                    if (tmp-&gt;elm != nullptr)
                    {
                        std::cout &lt;&lt; "delete " &lt;&lt; tmp-&gt;elm-&gt;toString() &lt;&lt; std::endl;
                        delete tmp-&gt;elm;
                    }
                    delete tmp;
                }
            }
        }
    }
    // 旋转哈希算法实现
    static uint32_t rotatingHash(std::vector&lt;uint8_t&gt; key, uint32_t prime)
    {
        uint32_t hash = key.size();
        for (uint32_t i = 0; i &lt; key.size(); ++i)
            hash = (hash &lt;&lt; 4) ^ (hash &gt;&gt; 28) ^ (uint32_t)(key[i]);
        return (hash % prime);
    }

    // 添加元素到集合
    bool add(elmBase *elm, bool force = false)
    {
        elmNode **node = __find__(elm);
        auto finally = [](elmNode **node, elmNode *linkPriv, elmBase *elm) -&gt; elmNode *
        {
            // 插入新节点到链表末尾
            if (linkPriv-&gt;next == nullptr)
            {
                linkPriv-&gt;next = elmNodeFactory(elm);
            }
            return nullptr;
        };

        // 使用lambda作为比较函数
        elmNode *targetNode = this-&gt;__link__(node, elm, [](elmNode *node, elmBase *tag) -&gt; bool
                                             { return *(node-&gt;elm) == *tag; }, finally);

        return targetNode == nullptr; // 返回是否插入成功
    }

    // 检查元素是否存在
    bool get(elmBase *elm)
    {
        elmNode **node = __find__(elm);
        elmNode *targetNode = this-&gt;__link__(node, elm,
                                             [](elmNode *node, elmBase *tag) -&gt; bool
                                             {
                                                 return *(node-&gt;elm) == *tag;
                                             });
        return targetNode != nullptr;
    }

    // 移除集合中的元素
    bool remove(elmBase *elm)
    {
        elmNode **node = __find__(elm);
        elmNode *ret = this-&gt;__link__(node, elm,
                                      [](elmNode *current, elmBase *tag) -&gt; bool
                                      {
                                          // 查找前驱节点执行删除
                                          if (current-&gt;next != nullptr &amp;&amp; *(current-&gt;next-&gt;elm) == *tag)
                                          {
                                              elmNode *tmp = current-&gt;next;
                                              current-&gt;next = current-&gt;next-&gt;next;
                                              delete tmp-&gt;elm; // 释放元素内存
                                              delete tmp;      // 释放节点内存
                                              return true;
                                          }
                                          return false;
                                      });
        return ret != nullptr;
    }

    // 调试用打印函数，显示哈希表结构
    void print()
    {
        std::cout &lt;&lt; "[HashTable Structure]" &lt;&lt; std::endl;
        for (int i = 0; i &lt; this-&gt;prime; i++)
        {
            std::cout &lt;&lt; "Bucket " &lt;&lt; i &lt;&lt; ": ";
            elmNode *node = this-&gt;setMap[i];
            while (node != nullptr)
            {
                std::cout &lt;&lt; node-&gt;elm-&gt;toString() &lt;&lt; " -&gt; ";
                node = node-&gt;next;
            }
            std::cout &lt;&lt; "NULL" &lt;&lt; std::endl;
        }
    }
};

// 数值类型元素实现
class number : public elmBase
{
    int data;

public:
    number(int data) : data(data) {}

    std::vector&lt;uint8_t&gt; getUint8Array() const override
    {
        // 将整型转换为字节数组
        return std::vector&lt;uint8_t&gt;(
            reinterpret_cast&lt;const uint8_t *&gt;(&amp;data),
            reinterpret_cast&lt;const uint8_t *&gt;(&amp;data) + sizeof(data));
    }

    std::string toString() override
    {
        return std::to_string(data);
    }
    ~number()
    {
    }
};

// 字符串类型元素实现
class string : public elmBase
{
    std::string data;

public:
    string(std::string data) : data(data) {}

    std::vector&lt;uint8_t&gt; getUint8Array() const override
    {
        // 将字符串内容转换为字节数组
        return std::vector&lt;uint8_t&gt;(data.begin(), data.end());
    }

    std::string toString() override
    {
        return data;
    }
    ~string()
    {
    }
};
</code></pre>
<h2>集合与元素的关系</h2>
<pre><code>若A表示一个集合，a是集合A中的元素，记作aA，读作a属于A；
若a不是集合A中的元素，则记作aA，读作a不属于A。
</code></pre>
<p dir="auto">未完待续</p>
]]></description><link>http://forum.d2learn.org/topic/83/离散数学-0x00</link><guid isPermaLink="true">http://forum.d2learn.org/topic/83/离散数学-0x00</guid><dc:creator><![CDATA[妈耶厥了]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[C++11: 核心语言特性0: 类型自动推导 - auto和decltype]]></title><description><![CDATA[<p dir="auto">https://en.cppreference.com/w/cpp/language/decltype</p>
<p dir="auto">image.png</p>
]]></description><link>http://forum.d2learn.org/topic/82/c-11-核心语言特性0-类型自动推导-auto和decltype</link><guid isPermaLink="true">http://forum.d2learn.org/topic/82/c-11-核心语言特性0-类型自动推导-auto和decltype</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item><item><title><![CDATA[使用d2x工具搭建了一个现代C++核心语言特性的代码练习项目mcpp-standard(类似rustlings)]]></title><description><![CDATA[<p dir="auto">打算从C++11-现代C++元年开始介绍其核心的语言特性(不包括标准库), 把每个特性制作一个代码练习, 然后通过d2x的检测程序进行代码检查...</p>
<p dir="auto">代码仓库: <a href="https://github.com/Sunrisepeak/mcpp-standard" rel="nofollow ugc">https://github.com/Sunrisepeak/mcpp-standard</a></p>
]]></description><link>http://forum.d2learn.org/topic/79/使用d2x工具搭建了一个现代c-核心语言特性的代码练习项目mcpp-standard-类似rustlings</link><guid isPermaLink="true">http://forum.d2learn.org/topic/79/使用d2x工具搭建了一个现代c-核心语言特性的代码练习项目mcpp-standard-类似rustlings</guid><dc:creator><![CDATA[SPeak]]></dc:creator><pubDate>Invalid Date</pubDate></item></channel></rss>