Header tunggal std::implementasi yang diharapkan menggunakan C++20.
Perpustakaan mengimplementasikan 2 proposal ini:
Implementasi ini memberikan apa yang diharapkan dalam namespace rd. Jadi, untuk penggunaan apa pun std::expected, gunakan rd::expected.
std::expected adalah mekanisme penanganan kesalahan. Ini sangat mirip dengan std::result karat. std::expected pada dasarnya berisi salah satu Hasil atau Kesalahan.
Mungkin ada 2 alasan untuk tidak "selalu" menggunakan pengecualian:
Saat menulis perpustakaan apa pun, ini menimbulkan masalah besar dalam penanganan kesalahan. Di perpustakaan, jika kita memilih untuk memberikan pengecualian pada kondisi kesalahan, kita membuat pilihan untuk pengguna perpustakaan. Kondisi kesalahan di perpustakaan bisa atau tidak bisa menjadi situasi luar biasa dalam konteks aplikasi yang menggunakan perpustakaan itu.
std::expected memberikan alternatif standar untuk pengecualian yang dapat digunakan untuk kondisi kesalahan yang tidak luar biasa dalam konteks aplikasi.
Meskipun demikian, perlu dicatat bahwa pengecualian sangat bagus untuk kondisi panik. Dan terdapat banyak kondisi panik yang jelas, dan hanya pengecualian yang harus digunakan.
error_code dulunya merupakan mekanisme penanganan kesalahan yang paling sederhana. Secara historis, error_code adalah bilangan bulat sederhana, yang tidak baik untuk konteks kesalahan yang kaya.
Saat ini, header C++ <system_error> menyediakan kode kesalahan yang lebih kaya. Namun, error_code menyebabkan monopoli saluran kembali. Oleh karena itu, nilai perlu dikeluarkan melalui saluran lain.
Ini juga memaksa Anda untuk menulis kondisi if setelah setiap pemanggilan fungsi.
std::expected menjamin bahwa itu tidak akan pernah kosong. yaitu, itu akan berisi salah satu nilai atau kesalahan pada suatu saat. Ini membuatnya sangat mudah digunakan.
auto get_file_handle (std::string_view path) -> rd::expected<file, fail_reason>;
auto read_file (file f) -> rd::expected<std::string, fail_reason>;
auto to_int (std::string str) -> rd::expected<int, fail_reason>;
auto increment ( int x) -> int;
auto read_int_with_increment (std::string_view path) -> rd::expected<int, fail_reason>{
return get_file_handle (path)
. and_then (read_file)
. and_then (to_int)
. transform (increment);
}
template < typename T, typename E>
class expected
T, E tidak bisa menjadi tipe referensi, karena tidak didukung di kertas juga.
using value_type = T;
using error_type = E;
using unexpected_type = unexpected<E>;
template < class U >
using rebind = expected<U, error_type>;
Konstruktor bawaan:
constexpr expected ();
Salin konstruktor:
constexpr expected (expected const &);
Pindahkan konstruktor:
constexpr expected (expected &&);
Konstruktor yang diharapkan:
U harus dapat dikonversi ke T, dan G harus dapat dikonversi ke E.
template < class U , class G >
constexpr expected (expected<U, G> const &);
template < class U , class G >
constexpr expected (expected<U, G> &&);
Konstruktor nilai:
Konstruktor untuk <T , E> yang diharapkan yang menerima nilai untuk menginisialisasi T (bagian nilai yang diharapkan).
template < class U = T>
constexpr expected (U&& v);
Konstruktor tak terduga:
Konstruktor untuk ekspektasi<T, E> yang menerima instance rd::unexpected untuk menginisialisasi E (bagian kesalahan yang diharapkan).
template < class G >
constexpr expected (unexpected<G> const &);
template < class G >
constexpr expected (unexpected<G> &&);
konstruktor in_place_t:
Konstruktor untuk <T, E> yang diharapkan yang menerima tag dan argumen in_place (untuk diteruskan) untuk menginisialisasi T.
template < class ... Args>
constexpr expected (std:: in_place_t , Args&&... args);
template < class U , class ... Args>
constexpr expected (std:: in_place_t , std::initializer_list<U>, Args&&... args);
konstruktor unexpect_t:
Konstruktor untuk ekspektasi<T, E> yang menerima tag rd::unexpect dan argumen (untuk diteruskan) untuk menginisialisasi E.
template < class ... Args>
constexpr expected (rd:: unexpect_t , Args&&... args);
template < class G , class ... Args>
constexpr expected (rd:: unexpect_t , std::initializer_list<G>, Args&&... args);
menyalin tugas:
constexpr expected& operator =(expected const &);
memindahkan tugas:
constexpr expected& operator =(expected &&);
Penetapan nilai:
Memberikan nilai pada yang diharapkan
template < class U = T>
constexpr expected& operator =(U&& rhs);
rd::tugas tak terduga:
Menetapkan kesalahan ke yang diharapkan
template < class G >
constexpr expected& operator =(unexpected<G> const &);
template < class G >
constexpr expected& operator =(unexpected<G> &&);
menempatkan:
Menerima argumen ke konstruktor nilai baru untuk yang diharapkan dan menetapkannya.
template < class ... Args>
constexpr T& emplace (Args&&... args);
template < class U , class ... Args>
constexpr T& emplace (std::initializer_list<U>, Args&&...);
menukar fungsi anggota dan fungsi teman
// For accessing T's members
// precondition: has_value() == true
constexpr T const * operator ->() const noexcept ;
// precondition: has_value() == true
constexpr T* operator ->() noexcept ;
// Getting reference to T
// precondition: has_value() == true
constexpr T const & operator *() const & noexcept ;
// precondition: has_value() == true
constexpr T& operator *() & noexcept ;
// precondition: has_value() == true
constexpr T&& operator *() && noexcept ;
// precondition: has_value() == true
constexpr T const && operator *() const && noexcept ;
// Query if value exists
constexpr explicit operator bool () const noexcept ;
constexpr bool has_value () const noexcept ;
// Get value, if not exists throws exception rd::bad_expected_access(error())
constexpr T const & value () const &;
constexpr T& value () &;
constexpr T&& value() &&;
constexpr T const && value() const &&;
// Get error, (undefined behavior if error not exists)
constexpr E const & error () const &;
constexpr E& error () &;
constexpr E&& error() &&;
constexpr E const && error() const &&;
// Get the value, if value doesn't exist return v
template < class U >
constexpr T value_or (U&& v) const &;
template < class U >
constexpr T value_or (U&& v) &&;
kemudian:
F harus dapat dipanggil dengan tipe nilai yang diharapkan dan harus mengembalikan yang diharapkan yang tipe kesalahannya harus E. Ia mengembalikan kesalahan yang diharapkan saat ini, jika ada kesalahan, yang lain mengembalikan hasil pemanggilan f dengan nilai.
template < class F >
constexpr auto and_then (F&& f) &;
template < class F >
constexpr auto and_then (F&& f) &&;
template < class F >
constexpr auto and_then (F&& f) const &;
template < class F >
constexpr auto and_then (F&& f) const &&;
atau_else:
F harus dapat dipanggil dengan tipe kesalahan yang diharapkan dan harus mengembalikan yang diharapkan yang tipe nilainya harus T.
Jika invoke_result_t<F, E>
adalah spesialisasi apa pun yang diharapkan (yang tipe nilainya harus sama dengan T), maka jika ada nilai di sana, nilai dikembalikan dengan dibungkus dalam invoke_result_t dari F jika tidak maka akan mengembalikan hasil pemanggilan f.
Jika invoke_result_t<F, E>
batal, maka jika ada kesalahan, maka F dipanggil dengan kesalahan. Harapan saat ini dikembalikan sebagai hasilnya.
template < class F >
constexpr auto or_else (F&& f) &;
template < class F >
constexpr auto or_else (F&& f) &&;
template < class F >
constexpr auto or_else (F&& f) const &;
template < class F >
constexpr auto or_else (F&& f) const &&;
mengubah:
F harus dapat dipanggil dengan tipe nilai yang diharapkan saat ini. Jika ekspektasi saat ini mengandung kesalahan, maka resultan ekspektasi berisi kesalahan tersebut, sebaliknya berisi hasil pemanggilan nilai ekspektasi saat ini dengan F.
template < class F >
constexpr auto transform (F&& f) &;
template < class F >
constexpr auto transform (F&& f) &&;
template < class F >
constexpr auto transform (F&& f) const &;
template < class F >
constexpr auto transform (F&& f) const &&;
transformasi_kesalahan:
F harus dapat dipanggil dengan jenis kesalahan yang diharapkan saat ini. Jika ekspektasi saat ini berisi nilai, maka resultan ekspektasi berisi nilai tersebut, jika tidak, berisi hasil pemanggilan kesalahan ekspektasi saat ini dengan F.
template < class F >
constexpr auto transform_error (F&& f) &;
template < class F >
constexpr auto transform_error (F&& f) &&;
template < class F >
constexpr auto transform_error (F&& f) const &;
template < class F >
constexpr auto transform_error (F&& f) const &&;
template < class U , class G >
constexpr friend bool operator ==(expected const &, expected<U, G> const &);
template < class U >
constexpr friend bool operator ==(expected const &, U const &);
template < class G >
constexpr friend bool operator ==(expected const &, rd::unexpected<G> const &);
template < typename T>
class unexpected
using value_type = T
Salin konstruktor:
constexpr unexpected (unexpected const &);
Pindahkan konstruktor:
constexpr unexpected (unexpected&&);
konstruktor in_place_t:
Ia menerima tag std::in_place dan membuat T dengan argumen.
template < typename ...Args>
constexpr unexpected (std:: in_place_t , Args&&... args);
template < typename U, typename ...Args>
constexpr unexpected (std:: in_place_t , std::initializer_list<U>, Args&&... args);
konstruktor nilai:
Membangun T dengan err.
template < typename Err>
constexpr unexpected (Err&& err);
// value(): gets the stored T value
constexpr T & value () &;
constexpr T const & value () const &;
constexpr T && value() &&;
constexpr T const && value() const &&;
template < class E2 >
friend constexpr bool operator ==(unexpected const & x, unexpected< E2 > const & y);
bad_expected_access berasal dari pengecualian. Menyimpan nilai kesalahan.
template < class E >
class bad_expected_access ;
E& error () & noexcept ;
E const & error () const & noexcept ;
E&& error() && noexcept ;
E const && error() const && noexcept ;
Ini hanyalah jenis tag, untuk menandakan kesalahan konstruksi yang diharapkan.
Perpustakaan juga memperlihatkan variabel tak terduga bertipe rd::unexpect_t.
inline constexpr unexpect_t unexpect{};