読者です 読者をやめる 読者になる 読者になる

Flat Leon Works

アプリやゲームを作ってます。

【C++ アイデア】ファイルのフォルダ分けをしつつ、ヘッダのインクルードを楽にする

C++ 技術

ファイルのフォルダ分けをすると#includeが面倒になる問題

プログラムの規模が大きくなってくると、当然ソースファイル、ヘッダファイルの数も増えていきます。ファイル数が増えてくるとファイルをカテゴリ別などでフォルダに分けたくなってきます。そのとき問題になってくるのが#includeによるファイルのインクルードです。

ファイルをフォルダ分けしたことによる問題

  • #includeのファイルパスがfoo/bar/baz.hのように長くなってしまう
  • 同じヘッダファイルでも#includeするファイルの場所によってファイルパスの指定が変わってくる

2番目は例を挙げると、foo/bar/baz.hにあるヘッダはfoo/bar/ディレクトリ内のファイルからは#include "baz.h"でインクルードできますが、foo/ディレクトリ内のファイルからは#include "bar/baz.h"でインクルードする必要があるということです。ファイルの場所によって#includeで指定するファイルパスが変わるのはとても面倒なことです。

ファイルを移動したことによる問題

  • 対象のファイルをインクルードしている箇所のファイルパスの記述をすべて修正しなくてはならない

解決法?1: フォルダ分けを諦める

srcディレクトリ内にフォルダを作らず、すべてのファイルをフラットに配置することです。この場合IDEのプロジェクトファイルツリー上でのみフォルダ分けを行ったりします。これは結構見かけるパターンです。

  • メリット
    • 特別な作業が発生しない
    • #includeの記述が楽
  • デメリット
    • ファイルのフォルダ分けができないのでファイルが見つけづらい(※IDE上ではプロジェクトツリー内でフォルダ分けができるので問題はない)
    • ファイル名の重複に気をつける必要がある

解決法?2: 楽に#includeをするのを諦める

ファイルのフォルダ分けを行い、#includeでは素直にフォルダも含めたファイルパスを指定します。

  • メリット
    • ファイルのフォルダ分けができる
    • ファイル名の重複をあまり気にしなくて良い
  • デメリット
    • #includeが面倒
    • ファイルを移動した場合、#includeのパスをすべて書き換える必要がある。

解決法3: インクルードパスを設定する

ビルド設定でインクルードパスを設定することで、フォルダ分けをしたとしても#include "hoge.h"のように単純にファイル名のみインクルードすることができるようになります。

  • メリット
    • ファイルのフォルダ分けを行うことができる
    • ファイルの移動がしやすい( インクルードパスを修正するだけ )
  • デメリット
    • フォルダごとにインクルードパスを設定しなくてはならない( 一括で設定できるIDEもあったりはする )
    • インクルードパスの設定方法がIDEごとに違う

解決法4: インクルード用のヘッダを用意する

ファイル名だけでインクルードできるようにするために、ヘッダファイルをインクルードするヘッダファイルを別に用意します(以下「インクルード用ヘッダ」と呼びます)。具体的には以下のようにします。

src/
  include/
    baz.h // 中身:#include "../foo/bar/baz.h"
  main.cpp
  foo/
    bar/
      baz.h
      baz.cpp

このような構成にした上でsrc/includeディレクトリにインクルードパスを設定することで、#include "foo/bar/baz.h"#include "baz.h"と書くことができるようになります。

  • メリット
    • #includeが楽に記述できる
    • ファイルのフォルダ分けを行うことができる
    • ファイルの移動がしやすい( 「インクルード用ヘッダ」の中身を修正するだけ )
  • デメリット
    • ファイル名の重複に気をつける必要がある
    • 「インクルード用ヘッダ」を用意するのが面倒

解決法5: 「インクルード用ヘッダ」を自動生成する

解決法4の「インクルード用ヘッダ」をPythonRubyなどのスクリプトで自動生成するようにします。「インクルード用ヘッダ」の中身は対象のヘッダファイルのパスから生成することができるので、スクリプトでファイル一覧を走査して一括で「インクルード用ヘッダ」を生成することができます。

  • メリット
    • #includeが楽に記述できる
    • ファイルのフォルダ分けを行うことができる
    • ファイルの移動がしやすい( スクリプトを叩くだけ )
  • デメリット
    • ファイル名の重複に気をつける必要がある
    • スクリプトを書く必要がある( ただし、一度書けばどのプロジェクトでも使い回すことができる )

まとめ

「インクルード用ヘッダ」をスクリプトで自動生成すると、ヘッダのインクルードを楽にしつつ、ファイルのフォルダ分けもできて幸せになれます。