Có thể tạo và thao tác các chuỗi trong thời gian biên dịch trong C ++ có một số ứng dụng hữu ích. Mặc dù có thể tạo các chuỗi thời gian biên dịch trong C ++, nhưng quá trình này rất phức tạp, vì chuỗi cần phải được khai báo là một chuỗi ký tự biến đổi, vd
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
Các hoạt động như nối chuỗi, trích xuất chuỗi con và nhiều thao tác khác, có thể dễ dàng được thực hiện như các thao tác trên chuỗi ký tự. Có thể khai báo chuỗi thời gian biên dịch thuận tiện hơn không? Nếu không, có một đề xuất trong các tác phẩm sẽ cho phép khai báo chuỗi thời gian biên dịch thuận tiện không?
Tại sao phương pháp tiếp cận hiện tại thất bại
Lý tưởng nhất, chúng tôi muốn có thể khai báo các chuỗi thời gian biên dịch như sau:
// Approach 1
using str1 = sequence<"Hello, world!">;
hoặc, sử dụng nghĩa đen do người dùng định nghĩa,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
nơi decltype(str2)
sẽ có một nhà constexpr
xây dựng. Có thể thực hiện phiên bản lộn xộn hơn của cách tiếp cận 1, lợi dụng thực tế là bạn có thể làm như sau:
template <unsigned Size, const char Array[Size]>
struct foo;
Tuy nhiên, mảng sẽ cần phải có liên kết bên ngoài, vì vậy để có cách tiếp cận 1 hoạt động, chúng ta sẽ phải viết một cái gì đó như thế này:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
Không cần phải nói, điều này rất bất tiện. Cách tiếp cận 2 thực sự không thể thực hiện được. Nếu chúng ta khai báo một constexpr
toán tử ( ), thì chúng ta sẽ chỉ định kiểu trả về như thế nào? Vì chúng ta cần toán tử trả về một chuỗi các ký tự, nên chúng ta sẽ cần sử dụng const char*
tham số để chỉ định kiểu trả về:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
Điều này dẫn đến một lỗi biên dịch, bởi vì s
không phải là a constexpr
. Cố gắng khắc phục điều này bằng cách làm như sau không giúp được gì nhiều.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
Tiêu chuẩn cho rằng dạng toán tử nghĩa đen cụ thể này được dành riêng cho các kiểu số nguyên và dấu phẩy động. Trong khi 123_s
sẽ làm việc, abc_s
sẽ không. Điều gì sẽ xảy ra nếu chúng ta bỏ hoàn toàn nghĩa đen do người dùng định nghĩa và chỉ sử dụng một constexpr
chức năng thông thường ?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
Như trước đây, chúng ta gặp vấn đề là mảng, bây giờ là một tham số cho constexpr
hàm, bản thân nó không còn là một constexpr
kiểu.
Tôi tin rằng có thể định nghĩa một macro tiền xử lý C lấy một chuỗi và kích thước của chuỗi làm đối số và trả về một chuỗi bao gồm các ký tự trong chuỗi (sử dụng BOOST_PP_FOR
, xâu chuỗi , đăng ký mảng và tương tự). Tuy nhiên, tôi không có thời gian (hoặc đủ quan tâm) để triển khai macro như vậy =)
constexpr
hàm và khởi tạo các mảng (do đó, concat, lớp nền, v.v.).
constexpr
chuỗi có thể được phân tích cú pháp trong thời gian biên dịch, do đó bạn có thể thực hiện các đường dẫn mã khác nhau tùy thuộc vào kết quả. Về cơ bản, bạn có thể tạo EDL trong C ++; các ứng dụng là khá vô hạn.