C++23 programlama dili: standartta başka neler ilginç?
C++23'ün bazı önemli özellikleri var ancak ayrıntılara ilginç eklemeler de var.
Duyuru
Bir hatırlatma olarak, C++23'ün en önemli özelliklerini burada bulabilirsiniz.
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.
C++23'ün en önemli özellikleri
Bunu Çıkarma ile C++23, çekirdek dilin küçük ama çok etkili bir özelliğini sunar. Bunun çıkarımı, Python'a benzer şekilde, örtülü olarak iletilen işaretçinin bir üye işlev tanımında açık hale getirilmesini mümkün kılar. Bu türetme sayesinde C++'taki CRTP veya Overload Pattern gibi bazı karmaşık teknikler çocuk oyuncağı haline gelir.
C++23 kütüphanesine birçok önemli ekleme yapılmıştır. Standart kütüphaneyi doğrudan kullanabilirsiniz import std; içe veya C++20 biçimindeki dizeleri içe aktarın std:
rint VE std:
rintln için başvurun. Ayrıca performans nedenleriyle düz ilişkisel kaplar da alıyoruz std::flat_map. std::flap_map bu bir drop-in değişimidir std::map. std:
ptional uyumluluk nedeniyle tekli bir arayüz içerecek şekilde genişletildi. Yeni veri türü std::expected zaten şekillendirilebilir bir arayüze sahiptir ve hata işleme için beklenen veya beklenmeyen bir değeri saklayabilir. Sayesinde std::mdspan çok boyutlu bir yay elde ederiz. std::generator Son olarak, bir sayı akışı oluşturmak için ilk somut eşyordam kullanılır. std::generator ranges kütüphanesinin bir parçasıdır ve C++23'te de geliştirilmiştir.
Daha detaylı bilgileri önceki makalelerimde bulabilirsiniz:
Temel dil
Sabit genişlikli kayan nokta türleri
Şu ana kadar C++ aşağıdaki veri türlerini desteklemektedir:
Yeni veri türleri başlıkta bulunur <stdfloat> tanımlandı. Uygulamanızın yeni veri türlerini destekleyip desteklemediğini kontrol etmek için önceden tanımlanmış bir makro kullanabilirsiniz.
Yığın izleme
Geçerli yığın izlemesi genellikle sorun giderme için çok faydalıdır. Yeni Stacktrace kütüphanesi tam olarak bunu sunuyor.
Kütüphane iki sınıftan oluşur:
sınıf basic_stacktrace yığın izinin tamamının veya belirli bir kısmının anlık görüntüsüdür.
Hala kafan mı karıştı?
Aşağıdaki basit örnekte main işlevi işlev func1 AÇIK, func1 aramalar func2 onun func2 aramalar func3 AÇIK.
// stacktrace1.cpp
#include <iostream>
#include <stacktrace>
void func3() {
std::cout << std::stacktrace::current() << 'n';
}
void func2() {
func3();
}
void func1() {
func2();
}
int main() {
func1();
}
func3 statik işlevi çağır current AÇIK std::stacktrace AÇIK. std::stacktrace için bir takma addır std::basic_stacktrace standart distribütör ile.
Program çalıştırıldığında yığın izleme bilgisi sağlar.
Programı Compiler Explorer'ı kullanarak derlemek gerçek bir zorluktu. Uygun GCC sürümünü ve kitaplıklarını bulmam biraz zaman aldı.
İşte g++ 13.1 için komut satırı: g++ -std=c++23 -lstdc++_libbacktrace.
Sayesinde std::stacktrace_entry yığın izlemeyi sorgulayabilirsiniz.
// stacktrace2.cpp
#include <iostream>
#include <stacktrace>
void func3() {
auto stacktrace = std::stacktrace::current();
for (const auto& entry: stacktrace) {
std::cout << "Description: " << entry.description() << 'n';
std::cout << "file: " << entry.source_file()
<< " and line: " << entry.source_line() <<'n';
std::cout << 'n';
}
}
void func2() {
func3();
}
void func1() {
func2();
}
int main() {
func1();
}
Çalışıyor func3 Yığın izleme girişleri arasında dolaşıyorum ve bunların açıklamasını, dosyasını ve satırını açıkça gösteriyorum.
C++23'ün geri kalan özellikleri hakkında sadece birkaç kelime yazacağım. Örnekler cppreference.com'dan alınmıştır.
Bir programın performansını etkileyebilecek iki özellikle başlamak istiyorum.
std::ulaşılamaz
Evet yapabilir std::unreachable Ulaşılamayan kodu işaretlemek için kullanın. std::unreachable öğesinin çağrılması tanımsız davranışla sonuçlanır.
// from https://en.cppreference.com/w/cpp/utility/unreachable
switch (xy)
{
case 128: [[fallthrough]];
case 256: [[fallthrough]];
case 512: /* ... */
tex.clear();
tex.resize(xy * xy, Color{0, 0, 0, 0});
break;
default:
std::unreachable();
}
std::move_only_function
C++11 ile var std::function. std::function polimorfik fonksiyonların bir sarmalayıcısıdır ve rastgele çağrıları kabul edebilir ve onlara bir ad verebilir. Çağrılabilirlerin tümü işlevler, işlev nesneleri veya lambdalar gibi işlevler gibi davranan varlıklardır.
Daha fazlası std::function buradan öğrenebilirsiniz: TR1 ve C++11'de işlevseldir.
Buna karşılık std::function Şekerler std::move_only_function sadece oluşturulabilir bir çağrılabilir elde edersiniz. Çağrılabilir nesne dosyada olabilir std::move_only_function Ek depolama gereksinimlerinden kaçınmak için.
// from https://en.cppreference.com/w/cpp/utility/functional/move_only_function
auto lambda = [task = std::move(packaged_task)]() mutable { task(); };
// std::function<void()> function = std::move(lambda); // Error
std::move_only_function<void()> function = std::move(lambda); // OK
std::byteswap
std::byteswap baytları bir değere dönüştür n. n bütünleyici olması gerekir.
Aşağıdaki program geçerlidir std::byteswap İLE.
// from https://en.cppreference.com/w/cpp/numeric/byteswap
#include <bit>
#include <concepts>
#include <cstdint>
#include <iomanip>
#include <iostream>
template<std::integral T>
void dump(T v, char term = 'n')
{
std::cout << std::hex << std::uppercase << std::setfill('0')
<< std::setw(sizeof(T) * 2) << v << " : ";
for (std::size_t i{}; i != sizeof(T); ++i, v >>= 8)
std::cout << std::setw(2)
<< static_cast<unsigned>(T(0xFF) & v) << ' ';
std::cout << std::dec << term;
}
int main()
{
static_assert(std::byteswap('a') == 'a');
std::cout << "byteswap for U16:n";
constexpr auto x = std::uint16_t(0xCAFE);
dump(x);
dump(std::byteswap(x));
std::cout << "nbyteswap for U32:n";
constexpr auto y = std::uint32_t(0xDEADBEEFu);
dump
;
dump(std::byteswap
);
std::cout << "nbyteswap for U64:n";
constexpr auto z = std::uint64_t{0x0123456789ABCDEFull};
dump(z);
dump(std::byteswap(z));
}
Son olarak programın çıktısı aşağıdadır.
Bir sonraki adım nedir?
Bir sonraki yazımda C++26'dan bahsedeceğim.
(Ben)
C++23 programlama dili: standartta başka neler ilginç?
C++23'ün bazı önemli özellikleri var ancak ayrıntılara ilginç eklemeler de var.
Duyuru
Bir hatırlatma olarak, C++23'ün en önemli özelliklerini burada bulabilirsiniz.


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.
C++23'ün en önemli özellikleri
Bunu Çıkarma ile C++23, çekirdek dilin küçük ama çok etkili bir özelliğini sunar. Bunun çıkarımı, Python'a benzer şekilde, örtülü olarak iletilen işaretçinin bir üye işlev tanımında açık hale getirilmesini mümkün kılar. Bu türetme sayesinde C++'taki CRTP veya Overload Pattern gibi bazı karmaşık teknikler çocuk oyuncağı haline gelir.
C++23 kütüphanesine birçok önemli ekleme yapılmıştır. Standart kütüphaneyi doğrudan kullanabilirsiniz import std; içe veya C++20 biçimindeki dizeleri içe aktarın std:
Daha detaylı bilgileri önceki makalelerimde bulabilirsiniz:
Temel dil
- C++23: Kesinti Bu, açık işaretçiler oluşturur
- C++23: Bunun çıkarımıyla sözdizimsel şeker
- C++23: Çekirdek dildeki küçük mücevherler
- C++23: çekirdek dildeki diğer küçük taşlar
- C++23: modülerleştirilmiş bir standart kitaplık ve iki yeni işlev
- Aralıklar: C++23 ile iyileştirmeler
- C++23: std::expected ile hataları işlemenin yeni bir yolu
- C++23: Dört yeni ilişkisel kapsayıcı
- C++23: çok boyutlu bir vizyon
Sabit genişlikli kayan nokta türleri
Şu ana kadar C++ aşağıdaki veri türlerini desteklemektedir:
- son ek yok: çift
- F son eki: şamandıra
- Son ek lo L: çift uzun

Yeni veri türleri başlıkta bulunur <stdfloat> tanımlandı. Uygulamanızın yeni veri türlerini destekleyip desteklemediğini kontrol etmek için önceden tanımlanmış bir makro kullanabilirsiniz.
Yığın izleme
Geçerli yığın izlemesi genellikle sorun giderme için çok faydalıdır. Yeni Stacktrace kütüphanesi tam olarak bunu sunuyor.
Kütüphane iki sınıftan oluşur:
- stacktrace_entry: Yığın izlemede bir değerlendirmenin temsili
- basic_stacktrace: tüm yığın izlemesinin veya belirli bir bölümünün anlık görüntüsü
sınıf basic_stacktrace yığın izinin tamamının veya belirli bir kısmının anlık görüntüsüdür.
Hala kafan mı karıştı?
Aşağıdaki basit örnekte main işlevi işlev func1 AÇIK, func1 aramalar func2 onun func2 aramalar func3 AÇIK.
// stacktrace1.cpp
#include <iostream>
#include <stacktrace>
void func3() {
std::cout << std::stacktrace::current() << 'n';
}
void func2() {
func3();
}
void func1() {
func2();
}
int main() {
func1();
}
func3 statik işlevi çağır current AÇIK std::stacktrace AÇIK. std::stacktrace için bir takma addır std::basic_stacktrace standart distribütör ile.
Program çalıştırıldığında yığın izleme bilgisi sağlar.
Programı Compiler Explorer'ı kullanarak derlemek gerçek bir zorluktu. Uygun GCC sürümünü ve kitaplıklarını bulmam biraz zaman aldı.
İşte g++ 13.1 için komut satırı: g++ -std=c++23 -lstdc++_libbacktrace.
Sayesinde std::stacktrace_entry yığın izlemeyi sorgulayabilirsiniz.
// stacktrace2.cpp
#include <iostream>
#include <stacktrace>
void func3() {
auto stacktrace = std::stacktrace::current();
for (const auto& entry: stacktrace) {
std::cout << "Description: " << entry.description() << 'n';
std::cout << "file: " << entry.source_file()
<< " and line: " << entry.source_line() <<'n';
std::cout << 'n';
}
}
void func2() {
func3();
}
void func1() {
func2();
}
int main() {
func1();
}
Çalışıyor func3 Yığın izleme girişleri arasında dolaşıyorum ve bunların açıklamasını, dosyasını ve satırını açıkça gösteriyorum.
C++23'ün geri kalan özellikleri hakkında sadece birkaç kelime yazacağım. Örnekler cppreference.com'dan alınmıştır.
Bir programın performansını etkileyebilecek iki özellikle başlamak istiyorum.
std::ulaşılamaz
Evet yapabilir std::unreachable Ulaşılamayan kodu işaretlemek için kullanın. std::unreachable öğesinin çağrılması tanımsız davranışla sonuçlanır.
// from https://en.cppreference.com/w/cpp/utility/unreachable
switch (xy)
{
case 128: [[fallthrough]];
case 256: [[fallthrough]];
case 512: /* ... */
tex.clear();
tex.resize(xy * xy, Color{0, 0, 0, 0});
break;
default:
std::unreachable();
}
std::move_only_function
C++11 ile var std::function. std::function polimorfik fonksiyonların bir sarmalayıcısıdır ve rastgele çağrıları kabul edebilir ve onlara bir ad verebilir. Çağrılabilirlerin tümü işlevler, işlev nesneleri veya lambdalar gibi işlevler gibi davranan varlıklardır.
Daha fazlası std::function buradan öğrenebilirsiniz: TR1 ve C++11'de işlevseldir.
Buna karşılık std::function Şekerler std::move_only_function sadece oluşturulabilir bir çağrılabilir elde edersiniz. Çağrılabilir nesne dosyada olabilir std::move_only_function Ek depolama gereksinimlerinden kaçınmak için.
// from https://en.cppreference.com/w/cpp/utility/functional/move_only_function
auto lambda = [task = std::move(packaged_task)]() mutable { task(); };
// std::function<void()> function = std::move(lambda); // Error
std::move_only_function<void()> function = std::move(lambda); // OK
std::byteswap
std::byteswap baytları bir değere dönüştür n. n bütünleyici olması gerekir.
Aşağıdaki program geçerlidir std::byteswap İLE.
// from https://en.cppreference.com/w/cpp/numeric/byteswap
#include <bit>
#include <concepts>
#include <cstdint>
#include <iomanip>
#include <iostream>
template<std::integral T>
void dump(T v, char term = 'n')
{
std::cout << std::hex << std::uppercase << std::setfill('0')
<< std::setw(sizeof(T) * 2) << v << " : ";
for (std::size_t i{}; i != sizeof(T); ++i, v >>= 8)
std::cout << std::setw(2)
<< static_cast<unsigned>(T(0xFF) & v) << ' ';
std::cout << std::dec << term;
}
int main()
{
static_assert(std::byteswap('a') == 'a');
std::cout << "byteswap for U16:n";
constexpr auto x = std::uint16_t(0xCAFE);
dump(x);
dump(std::byteswap(x));
std::cout << "nbyteswap for U32:n";
constexpr auto y = std::uint32_t(0xDEADBEEFu);
dump
dump(std::byteswap
std::cout << "nbyteswap for U64:n";
constexpr auto z = std::uint64_t{0x0123456789ABCDEFull};
dump(z);
dump(std::byteswap(z));
}
Son olarak programın çıktısı aşağıdadır.

Bir sonraki adım nedir?
Bir sonraki yazımda C++26'dan bahsedeceğim.
(Ben)