Çekirdek dil C++26: Küçük iyileştirmeler
Birkaç gönderide öne sürdüğüm Reflection ve Contracts'a yapılan büyük eklemelere ek olarak, C++26 için planlanan daha küçük, daha kullanışlı eklemeler de var.
Duyuru
Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.
Geçen hafta zaten joker karakterleri ve genişletilmiş karakter kümelerini göstermiştim ve bu sefer C++ standardına yapılan diğer eklemelerden bahsediyorum.
static_assert Eklenti
Her şeyden önce, burada sözdizimi var static_assert C++ 11'de:
static_assert(compile time predicate, unevaluated string)
C++26'da String, aşağıdaki özelliklere sahip, kullanıcı tanımlı bir veri türü olabilir:
// static_assert26.cpp
#include <iostream>
#include <format>
template <typename T, auto Expected, unsigned long Size = sizeof(T)>
constexpr bool ensure_size() {
static_assert(sizeof(T) == Expected, "Unexpected sizeof");
return true;
}
struct S {
int _{};
};
int main() {
std::cout << std::boolalpha << "C++11n";
static_assert(ensure_size<S, 1>());
std::cout << std::boolalpha << "C++26n";
static_assert(sizeof(S) == 1,
std::format("Unexpected sizeof: expected 1, got {}", sizeof(S)));
std::cout << 'n';
}
Das Template ensure_size ist so definiert, dass es drei Parameter akzeptiert: einen Datentyp T, eine erwartete Größe Expected und einen optionalen Parameter Size, der standardmäßig der Größe von T entspricht. Innerhalb der Funktion überprüft eine static_assert-Anweisung, ob die Größe von T gleich Expected ist. Wenn die Größen nicht übereinstimmen, schlägt die Kompilierung mit der Meldung Unexpected sizeof fehl. Die Funktion gibt true zurück, wenn die Zusicherung erfüllt ist.
Das Programm definiert dann eine einfache Struktur S, die ein einzelnes Integer-Element _ enthält. Diese Struktur wird verwendet, um die static_assert-Funktionalität zu demonstrieren.
In der main-Funktion gibt das Programm zunächst C++11 mit std::boolalpha in der Konsole aus, um boolesche Werte als true oder false zu formatieren. Anschließend wird static_assert mit aufgerufen, wodurch überprüft wird, ob die Größe von S 1 Byte beträgt. Da die Größe von S tatsächlich größer als 1 Byte ist, schlägt diese Zusicherung fehl und führt zu einem Kompilierungsfehler.
Als Nächstes gibt das Programm C++26 in der Konsole aus und verwendet eine weitere static_assert. Dieses Mal kommt std::format zum Einsatz. Wenn die Größe von S nicht 1 Byte, sondern 4 beträgt, schlägt die Kompilierung fehl.
Der Blick auf die GCC-Fehlermeldungen zeigt drei Fehler. std::format ist bisher nicht constexpr.
Pack-Indizierung
Die Pack-Indizierung ist wohl die Lieblings-Template-Verbesserung für die Freunde der Template-Metaprogrammierung.
Das folgende Beispiel basiert auf dem Proposal P2662R3.
// packIndexing.cpp
#include <iostream>
#include <string>
template <typename... T>
constexpr auto first_plus_last(T... values) -> T...[0] { T'yi döndürür...[0](değerler...[0] + değerler...[sizeof...(values)-1]); } int main() { std::cout code>
Verilen örnek, bir parametre paketinin ilk ve son elemanlarının toplamını hesaplayan bir fonksiyon şablonudur.
İşlev, herhangi bir T veri türünden değişken sayıda parametre alan bir şablon olarak tanımlanır. İşlevin dönüş türü, son dönüş türü sözdizimi kullanılarak belirtilir.
Fonksiyonun gövdesi parametre paketinin ilk ve son elemanlarının toplamını döndürür. İfade values...[0] ilk eleman e'ye erişir values...[sizeof...(values)-1] son öğeye erişir.
İşte programın çıktısı:
delete sebep ile
C++26 ile bir nedeniniz olabilir delete belirtmek. Bunun en iyi uygulama haline geleceğini varsayıyorum. Aşağıdaki program prosedürü açıklığa kavuşturmayı amaçlamaktadır.
// deleteReason.cpp
#include <iostream>
void func(double){}
template <typename T>
void func(T) = delete("Only for double");
int main(){
std::cout << 'n';
func(3.14);
func(3.14f);
std::cout << 'n';
}
fonksiyon func iki şekilde aşırı yüklenmiştir. İlk aşırı yük düzgün bir fonksiyondur. double parametre olarak kullanılır. Bu özellik sorunsuz bir şekilde kullanılabilir doublebuna argüman diyebilirsiniz.
İkinci aşırı yük ise her türlü veri tipini parametre olarak kabul edebilen bir modeldir. Ancak bu işlev dosyayla açıkça kullanılır. = deleteözel mesajla belirtici "Only for double" silindi. Bu, her örneğin farklı bir veri türüne sahip olacağı anlamına gelir. double bir derleme hatası oluşturur ve sağlanan mesaj görüntülenir.
içinde mainfonksiyon programı çağırır func argümanlı 3.14 hadi ama double VE. Bu çağrı geçerlidir ve şablon dışı aşırı yüklemeyi başlatır func AÇIK.
Program daha sonra şunu dener: func argümanlı 3.14f buna öyle de float VE. Modele dayalı olmayan bir ek yük olmadığından func bir tane var float kabul edildiğinde şablon işlevi başlatılacaktır. Ancak şablon işlevi, hariç tüm veri türleri için çalıştığından double silindi, bu çağrı “” mesajıyla derleme hatasına neden oluyorOnly for double“.
Bir sonraki adım nedir?
Bir sonraki yazımda C++26 kütüphanesinden bahsedeceğim.
(Ben)
Çekirdek dil C++26: Küçük iyileştirmeler
Birkaç gönderide öne sürdüğüm Reflection ve Contracts'a yapılan büyük eklemelere ek olarak, C++26 için planlanan daha küçük, daha kullanışlı eklemeler de var.
Duyuru
Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.
Geçen hafta zaten joker karakterleri ve genişletilmiş karakter kümelerini göstermiştim ve bu sefer C++ standardına yapılan diğer eklemelerden bahsediyorum.
static_assert Eklenti
Her şeyden önce, burada sözdizimi var static_assert C++ 11'de:
static_assert(compile time predicate, unevaluated string)
C++26'da String, aşağıdaki özelliklere sahip, kullanıcı tanımlı bir veri türü olabilir:
- Bir size() tamsayı üreten yöntem
- Bir data() tür karakterinin bir işaretçisini üreten yöntem, öyle ki
- İçindeki unsurlar hizalamak [data(), data()+size()) are valid. (p2741r3)
// static_assert26.cpp
#include <iostream>
#include <format>
template <typename T, auto Expected, unsigned long Size = sizeof(T)>
constexpr bool ensure_size() {
static_assert(sizeof(T) == Expected, "Unexpected sizeof");
return true;
}
struct S {
int _{};
};
int main() {
std::cout << std::boolalpha << "C++11n";
static_assert(ensure_size<S, 1>());
std::cout << std::boolalpha << "C++26n";
static_assert(sizeof(S) == 1,
std::format("Unexpected sizeof: expected 1, got {}", sizeof(S)));
std::cout << 'n';
}
Das Template ensure_size ist so definiert, dass es drei Parameter akzeptiert: einen Datentyp T, eine erwartete Größe Expected und einen optionalen Parameter Size, der standardmäßig der Größe von T entspricht. Innerhalb der Funktion überprüft eine static_assert-Anweisung, ob die Größe von T gleich Expected ist. Wenn die Größen nicht übereinstimmen, schlägt die Kompilierung mit der Meldung Unexpected sizeof fehl. Die Funktion gibt true zurück, wenn die Zusicherung erfüllt ist.
Das Programm definiert dann eine einfache Struktur S, die ein einzelnes Integer-Element _ enthält. Diese Struktur wird verwendet, um die static_assert-Funktionalität zu demonstrieren.
In der main-Funktion gibt das Programm zunächst C++11 mit std::boolalpha in der Konsole aus, um boolesche Werte als true oder false zu formatieren. Anschließend wird static_assert mit aufgerufen, wodurch überprüft wird, ob die Größe von S 1 Byte beträgt. Da die Größe von S tatsächlich größer als 1 Byte ist, schlägt diese Zusicherung fehl und führt zu einem Kompilierungsfehler.
Als Nächstes gibt das Programm C++26 in der Konsole aus und verwendet eine weitere static_assert. Dieses Mal kommt std::format zum Einsatz. Wenn die Größe von S nicht 1 Byte, sondern 4 beträgt, schlägt die Kompilierung fehl.
Der Blick auf die GCC-Fehlermeldungen zeigt drei Fehler. std::format ist bisher nicht constexpr.
Pack-Indizierung
Die Pack-Indizierung ist wohl die Lieblings-Template-Verbesserung für die Freunde der Template-Metaprogrammierung.
Das folgende Beispiel basiert auf dem Proposal P2662R3.
// packIndexing.cpp
#include <iostream>
#include <string>
template <typename... T>
constexpr auto first_plus_last(T... values) -> T...[0] { T'yi döndürür...[0](değerler...[0] + değerler...[sizeof...(values)-1]); } int main() { std::cout code>
Verilen örnek, bir parametre paketinin ilk ve son elemanlarının toplamını hesaplayan bir fonksiyon şablonudur.
İşlev, herhangi bir T veri türünden değişken sayıda parametre alan bir şablon olarak tanımlanır. İşlevin dönüş türü, son dönüş türü sözdizimi kullanılarak belirtilir.
Fonksiyonun gövdesi parametre paketinin ilk ve son elemanlarının toplamını döndürür. İfade values...[0] ilk eleman e'ye erişir values...[sizeof...(values)-1] son öğeye erişir.
İşte programın çıktısı:
delete sebep ile
C++26 ile bir nedeniniz olabilir delete belirtmek. Bunun en iyi uygulama haline geleceğini varsayıyorum. Aşağıdaki program prosedürü açıklığa kavuşturmayı amaçlamaktadır.
// deleteReason.cpp
#include <iostream>
void func(double){}
template <typename T>
void func(T) = delete("Only for double");
int main(){
std::cout << 'n';
func(3.14);
func(3.14f);
std::cout << 'n';
}
fonksiyon func iki şekilde aşırı yüklenmiştir. İlk aşırı yük düzgün bir fonksiyondur. double parametre olarak kullanılır. Bu özellik sorunsuz bir şekilde kullanılabilir doublebuna argüman diyebilirsiniz.
İkinci aşırı yük ise her türlü veri tipini parametre olarak kabul edebilen bir modeldir. Ancak bu işlev dosyayla açıkça kullanılır. = deleteözel mesajla belirtici "Only for double" silindi. Bu, her örneğin farklı bir veri türüne sahip olacağı anlamına gelir. double bir derleme hatası oluşturur ve sağlanan mesaj görüntülenir.
içinde mainfonksiyon programı çağırır func argümanlı 3.14 hadi ama double VE. Bu çağrı geçerlidir ve şablon dışı aşırı yüklemeyi başlatır func AÇIK.
Program daha sonra şunu dener: func argümanlı 3.14f buna öyle de float VE. Modele dayalı olmayan bir ek yük olmadığından func bir tane var float kabul edildiğinde şablon işlevi başlatılacaktır. Ancak şablon işlevi, hariç tüm veri türleri için çalıştığından double silindi, bu çağrı “” mesajıyla derleme hatasına neden oluyorOnly for double“.
Bir sonraki adım nedir?
Bir sonraki yazımda C++26 kütüphanesinden bahsedeceğim.
(Ben)