はじめに
列挙型とは、関連性の高い複数の定数(列挙子)をまとめて一つの型として定義することができるデータ型のことです。C++言語では、列挙型は次のように記述することができます。列挙型を使用することで、コードの可読性向上、型安全性の保障など、様々なメリットを享受できます。
enum class Color { Red = 1, Yellow = 3, Green = 5, Blue = 7 };
一方でC++言語では、列挙型⇔文字列・列挙値の変換操作が標準機能でサポートされていません。この制約が意外と厄介で、先述した変換操作を実装する際には、全ての列挙子に対応する条件分岐を不足なく記述しなければなりません。例えば「読み込んだ文字列を列挙子に変換する」関数の実装例を下記に示しますが、列挙子Red
に対する条件分岐、列挙子Yellow
に対する条件分岐...、とべた書きしなければならず、可読性や変更容易性の低い実装となってしまいます。
Color castFromStringToColor( const std::string enumerator_name ) {
if ( enumerator_name == "Red" ) return Color::Red;
else if ( enumerator_name == "Yellow" ) return Color::Yellow;
...
}
今回、列挙型⇔文字列・列挙値の変換をはじめとした操作を暗黙的に実行するような、専用のヘッダーライブラリを作成しました。本記事は、ライブラリの概要ならびに使用方法の紹介記事になります。
ヘッダーライブラリの概要
本ヘッダーライブラリで提供される機能一覧は下記の通りです。
- 列挙子の総数を取得する機能
- 列挙子を羅列した配列を取得する機能
- 列挙型⇔文字列・列挙値の変換を行う機能
ソースコードは下記リンクよりアクセス可能です。ヘッダーライブラリ本体(enum_converter.hpp
)は、src
ディレクトリに格納されています。
使い方
ユーザーはヘッダーライブラリをインクルードすることで、ヘッダーライブラリに定義されたフリー関数群にアクセスできるようになります。
#include<enum_converter.hpp>
enum class Color { Red = 1, Yellow = 3, Green = 5, Blue = 7 };
int32_t main( int32_t argc, char** argv ) {
std::cout << util::castToString<Color>( Color::Red ) << std::endl;
}
列挙子の総数の取得
getSize()
関数を用いることで、列挙型クラスが内包する列挙子の総数を取得できます。
constexpr auto size = util::getSize<Color>();
//=> 4
列挙子名リストの取得
getEnumeratorNameList()
関数を用いることで、列挙子名を羅列した配列を取得できます。
constexpr auto enumerator_name_list = util::getEnumeratorNameList<Color>();
// => { "Red", "Yellow", "Green", "Blue" }
列挙値リストの取得
getEnumeratorIndexList()
関数を用いることで、列挙値を羅列した配列を取得できます。
constexpr auto enumerator_index_list = util::getEnumeratorIndexList<Color>();
// => { 1, 3, 5, 7 }
列挙子リストの取得
getEnumeratorList()
関数を用いることで、列挙子を羅列した配列を取得できます。
constexpr auto enumerator_list = util::getEnumeratorList<Color>();
// => { Color::Red, Color::Yellow, Color::Green, Color::Blue }
文字列 or 列挙値から列挙子への変換
castToEnumerator()
関数を用いることで、文字列 or 列挙値を列挙子に変換できます。指定した文字列 or 列挙値に対応する列挙子が存在しない場合、エラーを発出します。
auto color_red = util::castToEnumerator<Color>( "Red" );
// => Color::Red
auto color_yellow = util::castToEnumerator<Color>( "Yellow" );
// => Color::Yellow
auto color_green = util::castToEnumerator<Color>( "Green" );
// => Color::Green
auto color_blue = util::castToEnumerator<Color>( "Blue" );
// => Color::Blue
auto color_red = util::castToEnumerator<Color>( 1 );
// => Color::Red
auto color_yellow = util::castToEnumerator<Color>( 3 );
// => Color::Yellow
auto color_green = util::castToEnumerator<Color>( 5 );
// => Color::Green
auto color_blue = util::castToEnumerator<Color>( 7 );
// => Color::Blue
列挙子から文字列への変換
castToString()
関数を用いることで、列挙子を文字列に変換できます。指定した列挙子に対応する文字列が存在しない場合、エラーを発出します。
auto color_red = util::castToString<Color>( Color::Red );
// => "Red"
auto color_yellow = util::castToString<Color>( Color::Yellow );
// => "Yellow"
auto color_green = util::castToString<Color>( Color::Green );
// => "Green"
auto color_blue = util::castToString<Color>( Color::Blue );
// => "Blue"
列挙子から列挙値への変換
castToInteger()
関数を用いることで、列挙子を列挙値に変換できます。指定した列挙子に対応するインデックスが存在しない場合、エラーを発出します。
auto color_red = util::castToInteger<Color>( Color::Red );
// => 1
auto color_yellow = util::castToInteger<Color>( Color::Yellow );
// => 3
auto color_green = util::castToInteger<Color>( Color::Green );
// => 5
auto color_blue = util::castToInteger<Color>( Color::Blue );
// => 7
注意点
- 本ライブラリは、C++20以上でのみ動作します。
- 本ライブラリは、負の列挙値をサポートしていません。
- デフォルト状態では、列挙値の上限は127に設定されています。列挙値の上限を引き上げたい場合、フリー関数のテンプレート引数(第二引数
NMAX
)にて、列挙値上限を指定してください。