C++ でコンパイル時に文字列を作成および操作できることには、いくつかの便利なアプリケーションがあります。C++ でコンパイル時の文字列を作成することは可能ですが、文字列を文字の可変長シーケンスとして宣言する必要があるため、プロセスは非常に面倒です。
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
文字列の連結、部分文字列の抽出などの操作は、文字列に対する操作として簡単に実装できます。コンパイル時の文字列をより便利に宣言することは可能ですか? そうでない場合、コンパイル時の文字列の便利な宣言を可能にする提案が進行中ですか?
既存のアプローチが失敗する理由
理想的には、次のようにコンパイル時の文字列を宣言できるようにしたいと考えています。
// Approach 1
using str1 = sequence<"Hello, world!">;
または、ユーザー定義リテラルを使用して、
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
どこdecltype(str2)
にconstexpr
コンストラクタがありますか。次のことができるという事実を利用して、アプローチ 1 のより複雑なバージョンを実装することが可能です。
template <unsigned Size, const char Array[Size]>
struct foo;
ただし、配列には外部リンケージが必要になるため、アプローチ 1 を機能させるには、次のように記述する必要があります。
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
言うまでもなく、これは非常に不便です。アプローチ 2 は、実際には実装できません。( ) リテラル演算子を宣言する場合constexpr
、戻り値の型をどのように指定しますか? 可変長の文字シーケンスを返す演算子が必要なので、const char*
パラメーターを使用して戻り値の型を指定する必要があります。
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
s
ではないため、コンパイル エラーが発生しますconstexpr
。以下を実行してこれを回避しようとしても、あまり役に立ちません。
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
標準では、この特定のリテラル演算子形式は整数型と浮動小数点型用に予約されていると規定されています。うまくいきます123_s
が、そうでabc_s
はありません。ユーザー定義のリテラルを完全に捨てて、通常のconstexpr
関数だけを使用するとどうなるでしょうか?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
前と同じように、配列 (現在はconstexpr
関数のパラメーター) 自体がもはやconstexpr
型ではないという問題に遭遇します。
文字列と文字列のサイズを引数として取り、文字列内の文字からなるシーケンスを返す C プリプロセッサ マクロを定義できるはずだと思います (. 、文字列化BOOST_PP_FOR
、配列添字などを使用)。ただし、そのようなマクロを実装する時間 (または十分な関心) がありません =)