💪

引数の意味を明示するstrong type

2024/10/09に公開

以下のようにbool型の引数を使っていませんか?

void createLevel(bool is_boss_level, bool add_save_point)
{
    if (is_boss_level && add_save_point)
    {
        // ...
    }
}

createLevel(true, false);

コールする側からすると、何がtrueなのか、何がfalseなのか全然分からないですよね。

以下のようにコメントが追加されるのはたまに見かけますが、この関数を呼ぶたびに、こういうコメントを書くのは大変です。

createLevel ( true   /*is_boss_level*/
            , false  /*add_save_point*/
            );

以下のようにそれっぽい名前の変数に代入して渡す手もあります。

const bool is_boss_level(true);
const bool add_save_point(false);

createLevel(is_boss_level, add_save_point);

でも毎回わざわざ変数を作成したくないですよね。しかも、同じbool型なので、順番が間違っていても、コンパイルエラーにならないです。順番のミスはレビューで見逃しやすいですよね。

こういう場合は、専用の型というstrong typeが必要です。

一番簡単なやり方はenum classを使うことです。普通のenumは暗黙的に型変換されてしまうため、駄目です。

enum class Level { Normal, Boss };
enum class AddSavePoint{ Yes, No };

void createLevel(Level level, AddSavePoint add_save_point)
{
    if (level == Level::Boss && add_save_point == AddSavePoint::Yes)
    {
        // ...
    }
}

createLevel(Level::Boss, AddSavePoint::No);
createLevel(AddSavePoint::No, Level::Boss); // コンパイルエラー!

変数によって、変数名とenum classの列挙子の名前を変えないといけなくなります。

でもこれだとコールする側から見ても、何を渡しているのかが分かりやすいです💪

順番を間違えて渡すとちゃんとコンパイルエラーになります💪💪

是非使ってみてください💪💪💪

あと、enumenum classの違いについては別の記事に書いていますので、是非こちらも見てみてください。
https://zenn.dev/spacesolver/articles/8b8b04455802b8


|cpp記事一覧へのリンク|

Discussion