組み込みC++最適化スキル
リソース制約の厳しい環境(RAM 64KB等)で要求される特殊なC++実装技術と設計判断基準。
L1: 禁止・許可ライブラリ(常に自動適用)
禁止ライブラリ・機能
コンテナ(動的メモリ確保)
❌ 禁止:
- •
std::vector,std::map,std::unordered_map - •
std::list,std::deque - •
std::set,std::unordered_set - •
std::string(動的確保が必要な場合)
✅ 許可 (代替):
- •
std::array(固定サイズ) - •
std::span(ビュー) - •
std::string_view(読み取り専用) - •Sorted Indexed Array パターン
スマートポインタ
❌ 禁止: std::unique_ptr, std::shared_ptr, std::weak_ptr
✅ 許可: 静的ライフサイクル設計、独自 Ref 構造体
I/O・並行処理
❌ 禁止: <iostream>, <fstream>, <thread>, <future>, <exception>
型消去
❌ 禁止: std::function (ヒープ確保の可能性)
✅ 許可: economic_function<Capacity> (静的バッファ版)
許可される標準ライブラリ
- •基本:
<cstdint>,<cstddef>,<limits>,<cassert>,<version>,<source_location> - •構造・型:
<array>,<span>,<string_view>,<optional>,<variant>,<tuple>,<bitset>,<initializer_list> - •ロジック:
<algorithm>,<utility>,<iterator>,<bit>,<compare>,<concepts>,<numbers> - •言語機能:
<coroutine>,<type_traits>,<new>(placement new目的のみ)
自動チェックツール
L1規則(禁止ライブラリ・機能)への準拠を自動的に検証するためのスクリプトが用意されています。
使用方法
bash
python3 .agent/skills/cpp_embedded/scripts/checker.py <ソースファイルまたはディレクトリ>
検証対象
- •禁止されたヘッダ(
<vector>,<iostream>等)のインクルード。 - •禁止された型や関数(
std::vector,std::unique_ptr,malloc,std::function等)の利用。
3. 判断基準 (Decision Guides)
1. 3-Tier分離の選択
システムの複雑度に応じた適切な分離レベルを選択する。
判断チェックリスト:
- •境界: このモジュールは別のシステム(プロセス、ハードウェア層等)と通信するか?
- •責務: 内部に3つ以上の独立した責務(Loader, Executor, Validator等)があるか?
- •テスト: サブモジュール単位でモック化してテストする必要があるか?
- •将来性: 将来的に実装を差し替える可能性があるか?
判断マトリクス:
| 基準 | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| 境界の種類 | システム間 | サブシステム内部 | 単一モジュール |
| 複雑度 | 高(システム全体) | 中(複数責務) | 低(単一責務) |
| テスト要求 | 独立したモック必要 | サブモジュール単体テスト | インライン単体テスト |
| 構成要素数 | - | 3個以上推奨 | 通常1〜2個 |
| 依存管理 | URI-DI / IPC | Harness / Static DI | 直接参照 |
2. インターフェイス分離の判断
判断チェックリスト:
- •差し替え: このモジュールの実装を将来差し替える可能性はあるか?
- •JITとインタープリタの切り替え → YES
- •固定アルゴリズムのユーティリティ → NO
- •テスト: モック化して単体テストする必要があるか?
- •複数実装: すでに複数の実装バリエーションが存在するか?
すべてNOの場合は、YAGNI原則に従いインターフェイスを分離せず直接実装する。
3. メモリ戦略の選択
判断チェックリスト:
- •サイズ: データの最大サイズはコンパイル時に決定可能か?
- •寿命: データはいつ作成され、いつ破棄されるか?
- •共有: 複数のモジュールが同じデータを参照するか?
- •変更: データは実行中に変更されるか?
パターン選択表:
| データ | サイズ | ライフサイクル | 適用パターン |
|---|---|---|---|
| 設定値 | コンパイル時定数 | プログラム全体 | constexpr 配列 |
| バッファ | 固定(例: 1024) | スタックスコープ | std::array |
| キャッシュ | 可変(上限あり) | オブジェクト寿命 | メンバ配列 + size_ |
| ROM参照 | 外部データ | - | std::span<const T> |
| 動的リスト | 実行時決定 | パーティション寿命 | パーティション確保 |
4. コンテナの選択
判断チェックリスト:
- •操作: 主な操作は検索か、追加・削除か、走査か?
- •頻度: データの更新頻度は?(初回のみ / 低頻度 / 高頻度)
- •順序: 要素の順序は重要か?
- •重複: 重複を許容するか?
コンテナ選択表:
| 用途 | 静的 | 動的(読み取り専用) | 動的(書き込み) |
|---|---|---|---|
| 配列 | std::array | std::span | パーティション配列 |
| Key-Value(検索) | constexpr配列 + 二分探索 | sorted_indexed_array_map | 設計見直し |
| 文字列 | constexpr char[] | std::string_view | パーティション確保 |
| 集合(Set) | std::bitset | ソート済み配列 | 設計見直し |
5. 型消去の戦略
std::function は使用禁止。
判断チェックリスト:
- •静的決定: 型は呼び出し側で完全に決定可能か? → テンプレート
- •キャプチャ: ラムダのキャプチャサイズは? →
sizeofで検証 - •複数型: 複数の異なる型を同一コンテナで扱う必要があるか? → インターフェイス
戦略決定:
- •型が静的に決定可能 → テンプレート化
- •コールバック(キャプチャ小)→
economic_function<N> - •コールバック(キャプチャ大)→ 設計見直し(キャプチャを削減せよ)
- •複数型の動的扱い → インターフェイス (Pure Virtual)
6. エラーハンドリングの戦略
判断チェックリスト:
- •回復: このエラーから回復する手段はあるか?
- •情報: エラーの詳細情報(メッセージ、コード)が必要か?
- •頻度: エラーは例外的か、それとも正常系の一部か?
パターン選択:
| エラー種別 | 回復可能性 | 推奨パターン | 例 |
|---|---|---|---|
| プログラミングエラー | 不可 | assert / panic | ヌルポインタ参照 |
| リソース不足 | 可 | std::optional<T> | メモリ不足 |
| 入力検証失敗 | 可 | status_code | 不正な引数 |
| 非同期エラー | 可 | coos::task<Result<T>> | I/O失敗 |
メモリ管理パターン
ポリシー・メモリ管理 {Policy_Memory}
原則:
- •ヒープ使用の原則禁止
- •必要な場合はパーティション管理(
dlmalloc,mspace) - •メモリパーティションごとに隔離
詳細: stdlib.md § 3.1
経済的な関数 (Economic Function)
std::function 代替のヒープレス・ラムダ活用技術。
- •固定サイズバッファによる配置
- •
static_assertによるサイズ検証 - •キャプチャサイズが制限を超えた場合はコンパイルエラー
コンテナ最適化
重いコンテナの回避と最適化された代替コンテナ。
- •
std::vector,std::mapの禁止と代替 - •
std::map代替のソート済み配列パターン