C ++ 'da derleme sırasında dizeler oluşturup işleyebilmenin birkaç yararlı uygulaması vardır. C ++ 'da derleme zamanı dizeleri oluşturmak mümkün olsa da, dizgenin değişken bir karakter dizisi olarak bildirilmesi gerektiğinden süreç çok zahmetlidir, örn.
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
Dize birleştirme, alt dize çıkarma ve diğerleri gibi işlemler, karakter dizileri üzerinde işlemler olarak kolayca uygulanabilir. Derleme zamanı dizgelerini daha uygun bir şekilde bildirmek mümkün müdür? Değilse, çalışmalarda derleme zamanı dizgilerinin uygun bildirimine izin verecek bir öneri var mı?
Mevcut Yaklaşımlar Neden Başarısız Oldu?
İdeal olarak, derleme zamanı dizelerini aşağıdaki gibi bildirebilmek isteriz:
// Approach 1
using str1 = sequence<"Hello, world!">;
veya kullanıcı tanımlı değişmez değerler kullanarak,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
decltype(str2)
bir constexpr
kurucu nerede olurdu . Aşağıdakileri yapabileceğiniz gerçeğinden yararlanarak yaklaşım 1'in daha karmaşık bir versiyonunu uygulamak mümkündür:
template <unsigned Size, const char Array[Size]>
struct foo;
Bununla birlikte, dizinin harici bağlantıya sahip olması gerekir, bu nedenle 1. yaklaşımı çalıştırmak için şuna benzer bir şey yazmamız gerekir:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
Söylemeye gerek yok, bu çok zahmetli. Yaklaşım 2'nin uygulanması aslında mümkün değildir. Bir ( constexpr
) değişmez operatörü bildirecek olsaydık, dönüş türünü nasıl belirtirdik? Operatörün değişken bir karakter dizisi döndürmesine ihtiyacımız olduğundan const char*
, dönüş türünü belirtmek için parametreyi kullanmamız gerekir :
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
Bu, bir derleme hatasıyla sonuçlanır, çünkü s
bir constexpr
. Aşağıdakileri yaparak bu sorunu çözmeye çalışmak pek yardımcı olmuyor.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
Standart, bu belirli değişmez operatör formunun tamsayı ve kayan nokta türleri için ayrıldığını belirtir. Çalışırken 123_s
işe abc_s
yaramazdı. Ya kullanıcı tanımlı değişmez değerleri tamamen kaldırırsak ve yalnızca normal birconstexpr
işlevi kullanırsak?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
Daha önce olduğu gibi, dizinin artık parametrenin bir parametresi olduğu sorunuyla karşılaşıyoruz. constexpr
fonksiyonun kendisinin artık bir constexpr
tür olmadığı .
Bir dizgeyi ve dizgenin boyutunu bağımsız değişken olarak alan ve dizedeki karakterlerden oluşan bir dizi döndüren ( BOOST_PP_FOR
dizgiselleştirme, dizi alt dizeleri ve benzerlerini kullanarak) bir C önişlemci makrosu tanımlamanın mümkün olduğuna inanıyorum . Ancak, böyle bir makroyu uygulamak için zamanım (veya yeterince ilgim) yok =)
constexpr
işlevler içinde kullanabilir ve dizileri başlatabilirsiniz (dolayısıyla, concat, substr vb.).
constexpr
sonuçlara bağlı olarak farklı kod yolları alabilmeniz için dizeler derleme sırasında ayrıştırılabilir. Esasen, C ++ içinde EDL'ler oluşturabilirsiniz; uygulamalar oldukça sınırsızdır.