C++26'ya genel bakış: temel dil
Bu görüntü, C++26'nın nasıl yapılandırıldığına dair ilk izlenimi sağlar.
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.
Bulanık sularda balık tutmak
Görüntünün yalnızca C++26'nın neye benzediğine dair ilk izlenimi vermesi amaçlanmaktadır. Önümüzdeki birkaç ay boyunca C++26 hakkında yazarken bunu gerektiği gibi uyarlayacağım. Örneğin, üç güçlü özellik; Yansıma, Sözleşmeler ve std::execution standardizasyonuna doğru büyük bir adım attılar. Bunun yerine, görüntüdeki desen eşleşmesini kasıtlı olarak görmezden geliyorum.
Yansıma veya sözleşmeler gibi çok etkili özellikler, minimum uygulanabilir ürün çevik fikrini hayata geçirir:
“Minimum Uygulanabilir Ürün (MVP), bir ürünün ilk müşteriler tarafından kullanılabilecek yeterli işlevselliğe sahip olan ve daha sonra gelecekteki ürün geliştirme için geri bildirim sağlayabilen bir versiyonudur.”
Bu, C++26'nın yansıma veya sözleşmeler gibi özellikler için yalnızca başlangıç noktası olduğu anlamına gelir. Mümkünse özellikleri çalışırken gösteriyorum. Pek çok özellik en yeni C++ derleyicilerinde zaten uygulanmıştır. Geri kalanı için prototip uygulamalarını umuyorum.
Ana dille başlayacağım.
Temel dil
Refleks
Yansıma, bir programın kendi yapısını ve davranışını inceleme, dikkate alma ve değiştirme yeteneğidir. Bu, C++'ta derleme zamanı programlamayı çok daha güçlü hale getirir. Bu yazıda sizi fazla teoriyle sıkmak istemiyorum. Bu yüzden size P2996R5 yansıma teklifinden en sevdiğim örneği göstereceğim.
Derslerimde sıklıkla yanıtlamak zorunda kaldığım bir soru şudur: Bir numaralandırıcıyı nasıl dizeye dönüştürebilirim?
// enumString.cpp
#include <iostream>
#include <experimental/meta>
#include <string>
#include <type_traits>
// start 'expand' definition
namespace __impl {
template<auto... vals>
struct replicator_type {
template<typename F>
constexpr void operator>>(F body) const {
(body.template operator()<vals>(), ...);
}
};
template<auto... vals>
replicator_type<vals...> replicator = {};
}
template<typename R>
consteval auto expand(R range) {
std::vector<std::meta::info> args;
for (auto r : range) {
args.push_back(std::meta::reflect_value(r));
}
return substitute(^__impl::replicator, args);
}
// end 'expand' definition
template<typename E>
requires std::is_enum_v<E> // (1)
constexpr std::string enum_to_string(E value) {
std::string result = "<unnamed>";
[:expand(std::meta::enumerators_of(^E)):] >> // (2)
[&]<auto e>{
if (value == [:e:]) {
result = std::meta::identifier_of(e); // (3)
}
};
return result;
}
int main() {
std::cout << 'n';
enum Color { red, green, blue };
std::cout << "enum_to_string(Color::red): " << enum_to_string(Color::red) << 'n';
// std::cout << "enum_to_string(Color(42)): " << enum_to_string(42) << 'n';
std::cout << 'n';
}
Bu örnekte deneysel özellikler (std::meta) normun. İşte programın çıktısı:
Kısaca fonksiyon modelinden bahsetmek istiyorum enum_to_string girmek. fonksiyon expand bu sadece bir geçici çözüm. İşlev çağrısı enum_to_string(Color(42)) işlev bir numaralandırma gerektirdiğinden bozulur: requires std::is_enum_v<E> (satır 1).
Satır (1) bir yansıma operatörü (^E) ve meta işlevini çağırın enum_to_std::meta::enumerators_of(^E) AÇIK. Son olarak, sözde birleştirici ([:refl:]) (2) satırında yansıma için dilbilgisi öğeleri. (3) satırındaki ikinci meta işlevi dizeyi oluşturur: std:meta::identifier_of(e)). Metafonksiyonlar, yansıma gibi derleme zamanında yürütülür.
Sözleşmeler
Bir sözleşme, yazılım bileşenleri için arayüzleri kesin ve doğrulanabilir bir şekilde belirtir. Bu yazılım bileşenleri ön koşulları, son koşulları ve değişmezleri karşılayan işlevlerdir.
İşte P2900 teklifinden basit bir örnek.
int f(const int x)
pre (x != 1) // a precondition assertion
post(r : r != 2) // a postcondition assertion; r refers to the return value of f
{
contract_assert (x != 3); // an assertion statement
return x;
}
fonksiyon f Bir ön koşulu, bir son koşulu ve bir değişmezi vardır. Ön koşul işlev çağrısından önce, son koşul işlev çağrısından sonra ve değişmez tam olarak çağrı sırasında kontrol edilir.
Fonksiyonu 1, 2 veya 3 numaralı argümanlarla çağırmak sözleşmeyi ihlal eder. Sözleşmenin ihlaline yanıt vermenin çeşitli yolları vardır.
void g()
{
f(0); // no contract violation
f(1); // violates precondition assertion of f
f(2); // violates postcondition assertion of f
f(3); // violates assertion statement within f
f(4); // no contract violation
}
C++26'nın temel dilinin yansıma ve sözleşmelerden çok daha fazlasını sunması mümkündür. Bunlardan kısaca bahsetmek ve ilgili tekliflerden bir kod pasajı sunmak istiyorum.
auto [x, y, _] = f();
Alt çizgi (_) “Umurumda değil” anlamına gelir. ve birden çok kez kullanılabilir.
static_assert(sizeof(S) == 1,
std::format("Unexpected sizeof: expected 1, got {}", sizeof(S))
C++26'daki şablonlarda birçok iyileştirme yapıldı. Benim favorim paket indeksleme:
template <typename... T>
constexpr auto first_plus_last(T... values) -> T...[0] {
return T...[0](values...[0] + values...[sizeof...(values)-1]);
}
int main() {
//first_plus_last(); // ill formed
static_assert(first_plus_last(1, 2, 10) == 11);
}
delete("Should have a reason");
Bir sonraki adım nedir?
Bir sonraki yazımda C++26 kütüphanesine genel bir bakış sunacağım.
(Mayıs)
C++26'ya genel bakış: temel dil
Bu görüntü, C++26'nın nasıl yapılandırıldığına dair ilk izlenimi sağlar.
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.
Bulanık sularda balık tutmak
Görüntünün yalnızca C++26'nın neye benzediğine dair ilk izlenimi vermesi amaçlanmaktadır. Önümüzdeki birkaç ay boyunca C++26 hakkında yazarken bunu gerektiği gibi uyarlayacağım. Örneğin, üç güçlü özellik; Yansıma, Sözleşmeler ve std::execution standardizasyonuna doğru büyük bir adım attılar. Bunun yerine, görüntüdeki desen eşleşmesini kasıtlı olarak görmezden geliyorum.
Yansıma veya sözleşmeler gibi çok etkili özellikler, minimum uygulanabilir ürün çevik fikrini hayata geçirir:
“Minimum Uygulanabilir Ürün (MVP), bir ürünün ilk müşteriler tarafından kullanılabilecek yeterli işlevselliğe sahip olan ve daha sonra gelecekteki ürün geliştirme için geri bildirim sağlayabilen bir versiyonudur.”
Bu, C++26'nın yansıma veya sözleşmeler gibi özellikler için yalnızca başlangıç noktası olduğu anlamına gelir. Mümkünse özellikleri çalışırken gösteriyorum. Pek çok özellik en yeni C++ derleyicilerinde zaten uygulanmıştır. Geri kalanı için prototip uygulamalarını umuyorum.
Ana dille başlayacağım.
Temel dil
Refleks
Yansıma, bir programın kendi yapısını ve davranışını inceleme, dikkate alma ve değiştirme yeteneğidir. Bu, C++'ta derleme zamanı programlamayı çok daha güçlü hale getirir. Bu yazıda sizi fazla teoriyle sıkmak istemiyorum. Bu yüzden size P2996R5 yansıma teklifinden en sevdiğim örneği göstereceğim.
Derslerimde sıklıkla yanıtlamak zorunda kaldığım bir soru şudur: Bir numaralandırıcıyı nasıl dizeye dönüştürebilirim?
// enumString.cpp
#include <iostream>
#include <experimental/meta>
#include <string>
#include <type_traits>
// start 'expand' definition
namespace __impl {
template<auto... vals>
struct replicator_type {
template<typename F>
constexpr void operator>>(F body) const {
(body.template operator()<vals>(), ...);
}
};
template<auto... vals>
replicator_type<vals...> replicator = {};
}
template<typename R>
consteval auto expand(R range) {
std::vector<std::meta::info> args;
for (auto r : range) {
args.push_back(std::meta::reflect_value(r));
}
return substitute(^__impl::replicator, args);
}
// end 'expand' definition
template<typename E>
requires std::is_enum_v<E> // (1)
constexpr std::string enum_to_string(E value) {
std::string result = "<unnamed>";
[:expand(std::meta::enumerators_of(^E)):] >> // (2)
[&]<auto e>{
if (value == [:e:]) {
result = std::meta::identifier_of(e); // (3)
}
};
return result;
}
int main() {
std::cout << 'n';
enum Color { red, green, blue };
std::cout << "enum_to_string(Color::red): " << enum_to_string(Color::red) << 'n';
// std::cout << "enum_to_string(Color(42)): " << enum_to_string(42) << 'n';
std::cout << 'n';
}
Bu örnekte deneysel özellikler (std::meta) normun. İşte programın çıktısı:

Kısaca fonksiyon modelinden bahsetmek istiyorum enum_to_string girmek. fonksiyon expand bu sadece bir geçici çözüm. İşlev çağrısı enum_to_string(Color(42)) işlev bir numaralandırma gerektirdiğinden bozulur: requires std::is_enum_v<E> (satır 1).
Satır (1) bir yansıma operatörü (^E) ve meta işlevini çağırın enum_to_std::meta::enumerators_of(^E) AÇIK. Son olarak, sözde birleştirici ([:refl:]) (2) satırında yansıma için dilbilgisi öğeleri. (3) satırındaki ikinci meta işlevi dizeyi oluşturur: std:meta::identifier_of(e)). Metafonksiyonlar, yansıma gibi derleme zamanında yürütülür.
Sözleşmeler
Bir sözleşme, yazılım bileşenleri için arayüzleri kesin ve doğrulanabilir bir şekilde belirtir. Bu yazılım bileşenleri ön koşulları, son koşulları ve değişmezleri karşılayan işlevlerdir.
İşte P2900 teklifinden basit bir örnek.
int f(const int x)
pre (x != 1) // a precondition assertion
post(r : r != 2) // a postcondition assertion; r refers to the return value of f
{
contract_assert (x != 3); // an assertion statement
return x;
}
fonksiyon f Bir ön koşulu, bir son koşulu ve bir değişmezi vardır. Ön koşul işlev çağrısından önce, son koşul işlev çağrısından sonra ve değişmez tam olarak çağrı sırasında kontrol edilir.
Fonksiyonu 1, 2 veya 3 numaralı argümanlarla çağırmak sözleşmeyi ihlal eder. Sözleşmenin ihlaline yanıt vermenin çeşitli yolları vardır.
void g()
{
f(0); // no contract violation
f(1); // violates precondition assertion of f
f(2); // violates postcondition assertion of f
f(3); // violates assertion statement within f
f(4); // no contract violation
}
C++26'nın temel dilinin yansıma ve sözleşmelerden çok daha fazlasını sunması mümkündür. Bunlardan kısaca bahsetmek ve ilgili tekliflerden bir kod pasajı sunmak istiyorum.
- Joker karakterler ve genişletilmiş karakter kümeleri
auto [x, y, _] = f();
Alt çizgi (_) “Umurumda değil” anlamına gelir. ve birden çok kez kullanılabilir.
- static_assert–Eklenti
static_assert(sizeof(S) == 1,
std::format("Unexpected sizeof: expected 1, got {}", sizeof(S))
C++26'daki şablonlarda birçok iyileştirme yapıldı. Benim favorim paket indeksleme:
template <typename... T>
constexpr auto first_plus_last(T... values) -> T...[0] {
return T...[0](values...[0] + values...[sizeof...(values)-1]);
}
int main() {
//first_plus_last(); // ill formed
static_assert(first_plus_last(1, 2, 10) == 11);
}
delete("Should have a reason");
Bir sonraki adım nedir?
Bir sonraki yazımda C++26 kütüphanesine genel bir bakış sunacağım.
(Mayıs)