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 constexprkonstruktor. 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 constexproperator ( ) 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 sbukan 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_sakan bekerja, abc_stidak akan. Bagaimana jika kita membuang semua literal yang didefinisikan pengguna, dan hanya menggunakan constexprfungsi 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 constexprfungsi, itu sendiri bukan lagi sebuah constexprtipe.
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 =)
constexprfungsi dan menginisialisasi array (oleh karena itu, concat, substr dll).
constexprstring 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.