Mampu membuat dan memanipulasi string selama waktu kompilasi di C ++ memiliki beberapa aplikasi yang berguna. Meskipun dimungkinkan untuk membuat string waktu kompilasi dalam C ++, prosesnya sangat rumit, karena string harus dideklarasikan sebagai urutan karakter yang bervariasi, misalnya
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
Operasi seperti penggabungan string, ekstraksi substring, dan banyak lainnya, dapat dengan mudah diimplementasikan sebagai operasi pada urutan karakter. Apakah mungkin untuk mendeklarasikan string kompilasi waktu dengan lebih mudah? Jika tidak, apakah ada proposal dalam karya yang memungkinkan deklarasi kompilasi waktu-waktu yang sesuai?
Mengapa Pendekatan yang Ada Gagal
Idealnya, kami ingin dapat mendeklarasikan string waktu kompilasi sebagai berikut:
// Approach 1
using str1 = sequence<"Hello, world!">;
atau, menggunakan literal yang ditentukan pengguna,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
di mana decltype(str2)
akan memiliki constexpr
konstruktor. Versi messier dari pendekatan 1 dimungkinkan untuk diterapkan, dengan memanfaatkan fakta bahwa Anda dapat melakukan hal berikut:
template <unsigned Size, const char Array[Size]>
struct foo;
Namun, array perlu memiliki hubungan eksternal, jadi untuk mendapatkan pendekatan 1 agar berfungsi, kita harus menulis sesuatu seperti ini:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
Tak perlu dikatakan, ini sangat merepotkan. Pendekatan 2 sebenarnya tidak mungkin diterapkan. Jika kita mendeklarasikan constexpr
operator ( ) literal, lalu bagaimana kita menentukan tipe pengembalian? Karena kita membutuhkan operator untuk mengembalikan urutan karakter variadik, maka kita perlu menggunakan const char*
parameter untuk menentukan tipe pengembalian:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
Ini menghasilkan kesalahan kompilasi, karena s
bukan a constexpr
. Berusaha mengatasi ini dengan melakukan hal berikut tidak banyak membantu.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
Standar menentukan bahwa bentuk operator literal khusus ini disediakan untuk tipe integer dan floating-point. Sementara 123_s
akan bekerja, abc_s
tidak akan. Bagaimana jika kita membuang semua literal yang didefinisikan pengguna, dan hanya menggunakan constexpr
fungsi biasa ?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
Seperti sebelumnya, kita mengalami masalah bahwa array, sekarang menjadi parameter constexpr
fungsi, itu sendiri bukan lagi sebuah constexpr
tipe.
Saya percaya itu harus mungkin untuk mendefinisikan makro preprocessor C yang mengambil string dan ukuran string sebagai argumen, dan mengembalikan urutan yang terdiri dari karakter dalam string (menggunakan BOOST_PP_FOR
, stringifikasi, array subscript, dan sejenisnya). Namun, saya tidak punya waktu (atau cukup minat) untuk mengimplementasikan makro =)
constexpr
fungsi dan menginisialisasi array (oleh karena itu, concat, substr dll).
constexpr
string dapat diuraikan selama waktu kompilasi, sehingga Anda dapat mengambil jalur kode yang berbeda tergantung pada hasilnya. Pada dasarnya, Anda dapat membuat EDL dalam C ++; aplikasi ini tidak terbatas.