C++20によるコンパイル時文字列についてのメモ
はじめに
C++といえばコンパイル時計算であるが、文字列型をテンプレートとして用いるにはちょっとした工夫が必要であった。この面倒さはC++20で改善され、C++標準のstd::string
やstd::string_view
で用いることができるわけではないが、お手軽に非型テンプレートとして文字列型を扱うことができるようになった。
そこで、文字列型をテンプレート引数として扱う際のもっとも基礎となる文字列型に関する実装をメモしておく。
実装
非型テンプレートとして利用可能な文字列型
非型テンプレートとして利用可能な文字列型については、上で示したサイトの条件を満たすように作成をすればいいため、実装としては以下のようにすればいい。文字列型ということで、加算についての2項演算子をオーバーロードしている。
ただ、この実装だけでは非型テンプレートとして利用する際に毎回string<char, 4>("abc")
のように記載する必要があり非常に面倒なため、以下のような推論補助も与えておく。
利用例としては、以下のようになる(クラステンプレートのテンプレート引数推論が超便利)。
型文字型を指定して対応する文字列を得る
文字列型を非型テンプレートとして利用したいとき、割と上記のstring
の実装だけでは機能的な不足が多い。代表的なものとしては<algorithm>
ヘッダの関数に相当する操作が挙げられるかもしれないが、ほとんどの関数はconstexpr
に対応しているため別に何も困らない。実際に対応に困るものとなると、例えば以下のようなメタ関数を作成して、結果の文字列(append_test::value
)を利用しようとしたとき、文字型がchar
の場合しか利用できなくなる。
これをどうにかするには、append_test
のテンプレート引数からL"-test"
という文字列を生成するように分岐をすればいいのだが、文字列を生成する処理は別途用意した方がいいだろう。これを実装する方法について少し悩んだが、以下を参照することでひとまず解決はした。やはり、原理上マクロを利用しないとスマートな記述方法は実現できないようである。
今回のstring
に対してであれば、以下のように実装をすればいいだろう。
これを用いることで、append_test
は以下のように実装しなおすことができ、あらゆる文字型に対応させることができる。
おわりに
これでコンパイル時の文字列操作が型を気にせず自由にできると思う。もちろん、サロゲートペアなど文字コード固有の面倒な扱いはあるが、必要であればその部分を特殊化すればいいだけである。そのうち、いい感じにコンパイル時文字列操作による何かを作りたいところである。