C ++ 23: Std ::

Adanali

Active member
C ++ 23: Std ::


  1. C ++ 23: Std ::

Veri türü std::eek:ptional C ++ 17'den mevcuttu. C ++ 23 ile daha ayrıntılı olarak tanıtacağım büyük bir monadik arayüz alıyor. Ancak o zamandan önce veri türüne hızlıca bakalım.











std::eek:ptional


Veri türü std::eek:ptional Hesaplamalar için sonuç verebilecek veritabanı sorgusu olarak çok pratiktir. Bu tür veriler başlığı gerektirir <optional>.








Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.







Çeşitli üreticiler ve işlev ile std::make_optional Sadece isteğe bağlı bir nesne olabilir optDeğerle veya değersiz tanımlayın. opt.emplace Sitede içerdiği değeri oluşturur ve opt.reset Konteynerin değerini yok eder. Yapabilirsiniz std::eek:ptional-Nontainer açıkça bir değeri olup olmadığını veya mantıksal bir ifadede kontrol edebileceğinizi sorar. opt.value Değeri döndürür ve opt.value_or Değeri veya önceden tanımlanmış bir değeri döndürür. Eğer opt Herhangi bir değer içermiyor, çağrı çözer opt.value A std::bad_optional_access-Aksption.

İşte basit bir örnek std::eek:ptional:



// optional.cpp

#include <optional>
#include <iostream>
#include <vector>

std::eek:ptional<int> getFirst(const std::vector<int>& vec){
if ( !vec.empty() ) return std::eek:ptional<int>(vec[0]);
else return std::eek:ptional<int>();
}

int main() {

std::cout << 'n';

std::vector<int> myVec{1, 2, 3};
std::vector<int> myEmptyVec;

auto myInt= getFirst(myVec);

if (myInt){
std::cout << "*myInt: " << *myInt << 'n';
std::cout << "myInt.value(): " << myInt.value() << 'n';
std::cout << "myInt.value_or(2017):" << myInt.value_or(2017) << 'n';
}

std::cout << 'n';

auto myEmptyInt= getFirst(myEmptyVec);

if (!myEmptyInt){
std::cout << "myEmptyInt.value_or(2017):" << myEmptyInt.value_or(2017) << 'n';
}

std::cout << 'n';

}


Kullanmak std::eek:ptional İşlevde getFirst. getFirst İlk öğeyi varken döndürür. Aksi takdirde bir tane alacaksınız std::eek:ptional-Nesne. . main-Kunksiyonun iki vektörü vardır. Her iki çağrı getFirst Açık ve verim std::eek:ptional-Ban. Durumunda myInt Nesnenin bir değeri vardır; durumunda myEmptyInt Nesnenin değeri yoktur. Program değerini gösterir: myInt VE myEmptyInt İLE. myInt.value_or(2017) Değeri döndürür, ancak myEmptyInt.value_or(2017) Varsayılan değeri döndürür.



İşte programın baskısı:









Monedic genişlemesi std::eek:ptional


C ++ 23'te std::eek:ptional Monadik operasyonlara opt.and_then, opt.transform VE opt.or_else genişletildi.

  • opt.and_then Belirtilen fonksiyonel çağrının sonucu varken geri döner, aksi takdirde bir boşluk std::eek:ptional.
  • opt.transform Bir tane verir std::eek:ptional dönüştürülmüş değeri veya boşluğu içeren geri std::eek:ptional.
  • opt.or_else Bunu verir std::eek:ptional Geri bir değer veya başka türlü belirli işlevin sonucu içeriyorsa.
Bu monadik operasyonlar, operasyonların bileşimine izin verir std::eek:ptional:



// optionalMonadic.cpp

#include <iostream>
#include <optional>
#include <vector>
#include <string>

std::eek:ptional<int> getInt(std::string arg) {
try {
return {std::stoi(arg)};
}
catch (...) {
return { };
}
}


int main() {

std::cout << 'n';

std::vector<std::eek:ptional<std::string>> strings = {"66", "foo", "-5"};

for (auto s: strings) {
auto res = s.and_then(getInt)
.transform( [](int n) { return n + 100;})
.transform( [](int n) { return std::to_string(n); })
.or_else([] { return std::eek:ptional{std::string("Error") }; });
std::cout << *res << ' ';
}

std::cout << 'n';

}


Akışa dayalı ön döngü, std::vector<std::eek:ptional<std::string>>. Her şeyden önce, işlev değişir getInt Bir tamsaya dönüştürülen her öğe 100 ekler, bir dizeye dönüştürür ve son olarak gösterir. İlk dönüşüm ne zaman int başarısız, dize Error iade edildi ve görüntülendi.









std::expected Monadik arayüzü zaten destekliyor.

std::expected


std::expected<T, E> İki değerden birini kaydetmek için bir yol sunar. Bir uygulama std::expected Daima bir değer içerir: veya türün beklenen değeri T veya türün beklenmedik değeri E. Bu tür kelime dağarcığının interstation ihtiyacı var <expected>. Sayesinde std::expected Bir değer veya hata döndüren işlevleri uygulayabilirsiniz. Depolanan değer doğrudan beklenen nesne tarafından doldurulmuş bellek içinde atanır. Dinamik bellek ataması yoktur.

std::expected benzer bir arayüze sahip std::eek:ptional. Aksine std::eek:ptional Şekerler std::exptected Bir hata mesajı döndürün.

Çeşitli üreticilerle beklenen bir nesne yapabilirsiniz exp Beklenen bir değerle tanımlayın. exp.emplace Yerinde içerdiği değeri oluşturun. Yapabilirsiniz std::expected-Nontainer açıkça bir değeri olup olmadığını veya mantıksal bir ifadede kontrol edebileceğinizi sorar. exp.value beklenen değeri döndürür e exp.value_or Beklenen değeri veya varsayılan değeri döndürür. Eğer exp Beklenmedik bir değeri var, çağrı çözer exp.value A std::bad_expected_access-Aksption.

std::unexpected Beklenmedik değeri temsil eder std::expected Kurtarıldı.



// expected.cpp

#include <iostream>
#include <expected>
#include <vector>
#include <string>

std::expected<int, std::string> getInt(std::string arg) {
try {
return std::stoi(arg);
}
catch (...) {
return std::unexpected{std::string(arg + ": Error")};
}
}


int main() {

std::cout << 'n';

std::vector<std::string> strings = {"66", "foo", "-5"};

for (auto s: strings) { // (1)
auto res = getInt(s);
if (res) {
std::cout << res.value() << ' '; // (3)
}
else {
std::cout << res.error() << ' '; // (4)
}
}

std::cout << 'n';

for (auto s: strings) { // (2)
auto res = getInt(s);
std::cout << res.value_or(2023) << ' '; // (5)
}

std::cout << 'n';

}


İşlev getInt Her dizeyi bir tamsaya dönüştürün ve std::expected<int, std::string> Geriye doğru. int beklenen e anlamına gelir std::string beklenmedik değer için. Döngüler için (satır 1 ve 2) dayanan iki aralık std::vector<std::string>. Beklenen değer (satır 3) veya beklenmedik değer (satır 4), döngü için (satır 1) ilk ışın içinde görüntülenir. Döngü (satır 2) için ikinci aralıkta beklenen veya varsayılan değer 2023 (satır 5) görüntülenir.









std::exptected İşlevlerin uygun bileşimi için monadik işlemleri destekler: exp.and_then, exp.transform, exp.or_else VE exp.transform_error.

  • exp.and_then Belirtilen işlev çağrısının sonucu, varken veya boşlukta döner std::expected.
  • exp.transform Bir tane verir std::expected dönüştürülmüş değeri veya boşluğu içeren geri std::expected.
  • exp.or_else verir std::exptected Geri bir değer veya başka türlü belirli işlevin sonucu içeriyorsa.
  • exp.transform_error beklenen değerini verir std::expected Eğer varsa geri. Aksi takdirde, std::expected Geriye doğru.
Aşağıdaki program önceki programa dayanmaktadır optionalMonadic.cpp. Esasen veri türüne sahibim std::eek:ptional Başından sonuna kadar std::expected değiştirildi.



// expectedMonadic.cpp

#include <iostream>
#include <expected>
#include <vector>
#include <string>


std::expected<int, std::string> getInt(std::string arg) {
try {
return std::stoi(arg);
}
catch (...) {
return std::unexpected{std::string(arg + ": Error")};
}
}

int main() {

std::cout << 'n';

std::vector<std::string> strings = {"66", "foo", "-5"};

for (auto s: strings) {
auto res = getInt(s)
.transform( [](int n) { return n + 100; })
.transform( [](int n) { return std::to_string(n); });
std::cout << *res << ' ';
}

std::cout << 'n';

}


Akışa dayalı ön döngü, std::vector<std::string>. Her şeyden önce, işlev değişir getInt Her dize bir tamsaya dönüşür, 100 ekler, bir dizede değişiklik yapar ve son olarak bunu gösterir. İlk dönüşüm bir tamsaya başarısız olursa, karakter zinciri olur arg + ": Error" iade edildi ve görüntülendi.









Sırada ne var?


Dört üyelik kapsayıcıları std::flat_map, std::flat_multimap, std::flat_set VE std::flat_multiset C ++ 23'te, sipariş edilen dernek konteynırlarının basit bir yerine geçiyorlar std::map,std::multimap, std::set VE std::multiset. C ++ 23'te bir nedenden dolayı var: performans.


(harita)
 
Üst