こんにちは、高木です。
これまではPHPで関数宣言や型の定義を生成してきました。今回は定数を生成することにします。定数といってもリテラルのことではなく、const、constexpr、constinit、および#defineによる定義を自動生成します。
まずはいつものように、必要な情報を格納する配列を定義することから始めます。
0 1 2 3 4 5 6 7 8 |
<?php $pi_info = [ 'name' => 'pi', 'value' => '3.1415926535897932384626433832795', 'type' => 'float', ]; ?> |
上の配列は円周率の定数を生成するための配列です。PHPには円周率を取得するpi関数やM_PIという定数があります。しかし、それらPHPの関数や定数を使うと、PHPのfloat型の精度に依存してしまいます。long double型や__float128型などを使う場合は適切なサフィックスを付ける必要があります。
また、キー’valie’の値には直値以外の式を指定することもできます。ただし、定数式以外を指定した場合は、constexprなどは使えなくなりますので要注意です。
では、この配列を使って定数定義を生成するコードを作っていきましょう。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php function make_constant(array $info, string $mode = 'constexpr'): string { $name = $info['name']; $value = $info['value']; if (array_key_exists('type', $info)) $type = $info['type']; else $type = 'auto'; if ($mode === '#define') { return "#define $name $value" . PHP_EOL; } return "$mode $type $name = $value;" . PHP_EOL; } ?> |
ここで定義したmake_constant関数は、引数として先ほどの$pi_infoのような配列$infoと、どのような方法で定数定義を行うかを指定する$modeを受け取ります。$modeには’#define’、’const’、’constexpr’、または’constinit’を指定することを想定していますが、エラーチェックはとくに行っていませんので、volatileや記憶クラス指定子などを指定することもできます。
また、引数として渡した配列にキー’type’が含まれていなければautoとみなしています。$modeに’#define’を指定した場合はキー’type’は単に無視しています。
以下、簡単に使用例を挙げておきます。
0 1 2 3 4 5 |
<?= make_constant($pi_info, '#define'); ?> <?= make_constant($pi_info, 'const'); ?> <?= make_constant($pi_info, 'constinit'); ?> <?= make_constant($pi_info); ?> |
各モードの振る舞いを見るために、4行並べて書いてみました。実際のプログラムでこんなことをすると名前が衝突しますので避けてください。
前処理結果は次のようになります。
0 1 2 3 4 5 |
#define pi 3.1415926535897932384626433832795 const float pi = 3.1415926535897932384626433832795; constinit float pi = 3.1415926535897932384626433832795; constexpr float pi = 3.1415926535897932384626433832795; |
こんな感じになります。
まだいろいろ工夫の余地があると思いますので、機会があれば拡張してみることにします。