この記事のポイント

  • enum class優先がレビュー標準である理由を整理
  • 通常enumの暗黙変換・スコープ汚染問題を実務でどう検出するか解説
  • 実務コード改善例とレビュー観点を提示

C++におけるenumの二系統

C++では以下2種類のenumが存在しています。

構文 特徴
enum C由来、暗黙int変換、スコープ外部流出
enum class C++11以降、スコープ限定、暗黙変換禁止、型安全

歴史的背景

  • Cとの互換維持のためenumは残存
  • C++11以降、型安全文化徹底のためenum class導入

なぜenum class優先がレビュー標準なのか

① 暗黙int変換防止

enum Color { Red, Green, Blue };
int n = Red;  // 暗黙int変換が許容
  • 意味の異なるint型と混同されやすい
  • 演算・比較の誤用バグが生まれやすい

② スコープ汚染防止

enum Status { OK, Error, Unknown };
Status s = OK;  // グローバルスコープ直載せ
  • 定数名衝突がプロジェクト規模拡大で多発

③ 型安全性向上

enum class Status { OK, Error, Unknown };
int n = Status::OK;  // エラー: 暗黙変換禁止
  • 意図しない混在を構文でブロック
  • スコープ限定により衝突防止

レビューでの基本指針

判定対象 レビュー指針
enum 原則禁止
enum class 常用標準
暗黙変換 強制禁止
定数名衝突 enum classで封じる

良い実装例

良い例:enum class標準化
enum class Permission {
    Read,
    Write,
    Execute
};

Permission p = Permission::Read;

if (p == Permission::Write) {
    // 書き込み権限処理
}

良い設計理由

  • 暗黙int変換なし
  • スコープ汚染なし
  • 定数名が限定範囲に閉じ込められる

レビュー観点

レビューアーは次を確認する。

  • enum classを原則採用しているか
  • 暗黙int変換を一切許容していないか
  • スコープ汚染が発生していないか
  • enum使用歴史コードは段階移行提案が進行しているか
  • 既存enum互換部分は型明示キャストで明文化しているか

良くない実装例: ケース1

悪い例:古いenum使用
enum Permission { Read, Write, Execute };
Permission p = Read;
@Reviewer
通常enumは使用禁止です。enum classに置き換えてください。
@Reviewer
定数名がスコープ汚染されています。

改善例

改善例:enum class化
enum class Permission { Read, Write, Execute };
Permission p = Permission::Read;

ケース2: 暗黙変換バグ温床

悪い例:int混入
enum Permission { Read, Write, Execute };
Permission p = Read;
int level = p;  // 暗黙変換
@Reviewer
enumからintへの暗黙変換は型安全性を崩壊させます。enum class適用で禁止しましょう。

改善例

改善例:暗黙変換排除
enum class Permission { Read, Write, Execute };
Permission p = Permission::Read;
// int型利用時は意図的キャストを明示
int level = static_cast<int>(p);  // 必要な時だけ明示変換

ケース3: スコープ汚染の副作用

悪い例:別enumとの衝突
enum UserState { Active, Inactive };
enum TaskState { Active, Completed };
@Reviewer
定数名Activeが衝突しています。enum class適用でスコープ分離してください。

改善例

改善例:enum classでスコープ隔離
enum class UserState { Active, Inactive };
enum class TaskState { Active, Completed };

ケース4: enum classでのint変換時に理由不明瞭

悪い例:キャスト理由不明
enum class Status { OK, NG };
int val = static_cast<int>(Status::OK);
@Reviewer
キャスト理由(外部API互換など)をコメント付記してください。

改善例

改善例:理由付記
int val = static_cast<int>(Status::OK);  // 外部プロトコル整数定義との互換用

int変換は最小限・理由明記が鉄則


ケース5: 古いAPI互換用enum混在

悪い例:古いAPI境界
enum OldFlag { FLAG_A = 1, FLAG_B = 2 };

void callLegacy(int flag);
callLegacy(FLAG_A);
@Reviewer
内部コードはenum class移行し、API境界でint変換責務を分離してください。

改善例

改善例:内部型安全・境界型変換
enum class Flag { A = 1, B = 2 };

void callLegacy(int flag);
Flag f = Flag::A;
callLegacy(static_cast<int>(f));

enum class導入はレビュー技術向上の登竜門

課題領域 enum classで防止できるリスク
型崩壊 int混入事故
スコープ汚染 定数名衝突
レビューコスト 型探索負荷
保守性 将来の値追加容易

観点チェックリスト


まとめ

レビューアーの役割は常にこう自問することです:

「enum classで安全性設計ができているか?」

  • C++の型安全文化ではenum classはほぼ必須
  • 通常enumは設計負債化しやすい

enum class採用=長期保守コスト削減設計です。
レビューで残存enumを必ず検出・移行提案できる力量が重要になります。