最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++使用expected實現(xiàn)優(yōu)雅的錯誤處理

 更新時間:2023年06月13日 10:29:08   作者:L_B__  
C++ 中提供了很多中方式進行錯誤處理。無論是通過拋異常還是通過錯誤碼,標(biāo)準(zhǔn)庫都提供相應(yīng)的調(diào)用,今天本文為大家介紹的是使用expected進行錯誤處理,感興趣的可以了解一下

使用expected進行錯誤處理

C++ 中提供了很多中方式進行錯誤處理。無論是通過拋異常還是通過錯誤碼,標(biāo)準(zhǔn)庫都提供相應(yīng)的調(diào)用。

  • 通過 try catch 以拋出異常的方式進行處理,這種方式很多人會覺得看起來可讀性很差(包括我),并且由于缺少異常規(guī)約(某些異常必須捕獲),容易出現(xiàn) bug,而且異常的傳遞很多時候可能伴隨動態(tài)分配內(nèi)存,這是一筆不小的開銷。
  • 通過 error_code 作為返回值判斷,這種方式雖然看似簡單易用,但是由于 C++ 中并未對 error_code 作過多的規(guī)范,使用起來并不方便,很多時候還是傾向于自定義一些枚舉作為自己的 error_code,但是由于缺少多返回值的語法(當(dāng)然如果C++版本比較高可用使用tuple以及解構(gòu)的語法實現(xiàn)),如果把錯誤碼作為返回值,那么原本的數(shù)據(jù)返回就只能函數(shù)參數(shù)傳遞引用的形式返回了。當(dāng)然,如果不考慮函數(shù)返回值的具體錯誤信息,可以使用 C++17 的 optional 。

由于 optional 無法包含具體的錯誤信息,expected 橫空出世,在 C++23 開始納入標(biāo)準(zhǔn)。如果你的C++版本較低,可以使用第三方開源的 expected 庫:github.com/TartanLlama/expected

下面我會以一個例子把第三方庫中的 expected 庫的使用方式介紹給大家。

expected 使用實例

由于該第三方庫是 head-only 的,所以你只需要進到GitHub倉庫把對應(yīng)的頭文件復(fù)制過來,便可引入使用。

下面是示例代碼,樣例是 cppreference 中的。

#include "expected.h"
#include <iomanip>
#include <iostream>
#include <string>
?
enum class parse_error
{
    invalid_input,
    overflow
};
?
tl::expected<double, parse_error> parse_number(std::string_view& str)
{
    const char* begin = str.data();
    char* end;
    double retval = std::strtod(begin, &end);
?
    if (begin == end)
        return tl::unexpected(parse_error::invalid_input);
    else if (std::isinf(retval))
        return tl::unexpected(parse_error::overflow);
?
    str.remove_prefix(end - begin);
    return retval;
}
?
int main()
{
    auto process = [](std::string_view str) {
        std::cout << "str: " << std::quoted(str) << ", ";
        if (const auto num = parse_number(str); num)
        {
            std::cout << "value: " << *num << '\n';
            // If num did not have a value, dereferencing num
            // would cause an undefined behavior, and
            // num.value() would throw std::bad_expected_access.
            // num.value_or(123) uses specified default value 123.
        }
        else if (num.error() == parse_error::invalid_input)
        {
            std::cout << "error: invalid input\n";
        }
        else if (num.error() == parse_error::overflow)
        {
            std::cout << "error: overflow\n";
        }
        else
        {
            std::cout << "unexpected!\n";// or invoke std::unreachable();
        }
    };
?
    for (auto src : {"42", "42abc", "meow", "inf"})
        process(src);
}

上面的代碼如果想要跑通,情確保C++版本至少是C++17,因為其中用到了 string_view 以及更智能的自動類型推導(dǎo)(如果低于這個幫會導(dǎo)致unexpected需要指定明確的error類型)。

函數(shù)式的接口

  • and_then:傳入一個回調(diào),在沒有錯誤的時候調(diào)用,該回調(diào)的返回值是新的 expected 值(可以控制err)。如果有錯誤返回原 expected 值。
  • or_else:傳入一個回調(diào),在有錯誤的時候調(diào)用,該回調(diào)的返回值是新的 expected 值(可以控制err),并且回調(diào)的參數(shù)是對應(yīng)的錯誤類型。如果沒有錯誤返回原 expected 值。
  • transform/map:transform 是C++23標(biāo)準(zhǔn)中規(guī)定的接口,而該第三方庫作者又實現(xiàn)了一個名為map的接口,這兩者效果是一致的。傳入一個回調(diào),在沒有錯誤的時候調(diào)用,回調(diào)的參數(shù)和返回值都不牽扯 expected 值,只是作值的變換,所以無法控制新的 expected 的 err 值。如果有錯誤則返回原 expected 值。
  • transform_error/map_error:同上,但回調(diào)的調(diào)用時機和參數(shù)于 or_else 相同,但是需要注意的是,回調(diào)的返回值并不具備任何效用,也就是說如果 transform_error 中的回調(diào)被調(diào)用,那么返回的仍然是原本包含錯誤信息的 expected 值。

簡單示例如下:

#include "expected.h"
#include <iostream>
#include <string>
?
enum class parse_error
{
    invalid_input,
    overflow
};
?
tl::expected<double, parse_error> parse_number(std::string_view& str)
{
    const char* begin = str.data();
    char* end;
    double retval = std::strtod(begin, &end);
?
    if (begin == end)
        return tl::unexpected(parse_error::invalid_input);
    else if (std::isinf(retval))
        return tl::unexpected(parse_error::overflow);
?
    str.remove_prefix(end - begin);
    return retval;
}
?
int main()
{
    auto sv = std::string_view{"0"};
    auto result = parse_number(sv)
                      .and_then([](double x) {
                         ?return tl::expected<double, parse_error>(x + 1);
                      })
                      .map([](double x) {
                         ?return x + 1;
                      })
                      .transform([](double x) {
                         ?return x + 1;
                      });
    if (result)
        std::cout << *result << "\n";
    auto result2 = parse_number(sv)
                     ? .and_then([](double x) {
                         ? //自己構(gòu)造了一個錯誤
                         ? tl::expected<double, parse_error> ret = tl::unexpected<parse_error>(parse_error::invalid_input);
                         ? return ret;
                     ? })
                     ? .or_else([](parse_error err) {
                         ? if (err == parse_error::invalid_input)
                         ? {
                             ? std::cout << "invalid error\n";
                         ? }
                         ? //自己構(gòu)造了一個錯誤
                         ? tl::expected<double, parse_error> ret = tl::unexpected<parse_error>(parse_error::overflow);
                         ? return ret;
                     ? })
                     ? .transform_error([](parse_error err) {
                         ? if (err == parse_error::overflow)
                         ? {
                             ? std::cout << "overflow error\n";
                         ? }
                         ? return 32432.4324;
                     ? }).map([](double x){
                         ? return x+1;
                     ? });
    if (result2)
    {
        std::cout << *result2;
    }
}

到此這篇關(guān)于C++使用expected實現(xiàn)優(yōu)雅的錯誤處理的文章就介紹到這了,更多相關(guān)C++錯誤處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言直接選擇排序算法詳解

    C語言直接選擇排序算法詳解

    直接選擇排序就是遍歷整個數(shù)組,每遍歷一遍的目的是找出該數(shù)組中的最大數(shù)和最小數(shù)對應(yīng)的下標(biāo),然后將最小數(shù)和數(shù)組的第一個數(shù)進行交換,最大數(shù)和數(shù)組的最后一個數(shù)進行交換,然后縮小范圍再次遍歷
    2022-08-08
  • C++中的構(gòu)造函數(shù)與析造函數(shù)詳解

    C++中的構(gòu)造函數(shù)與析造函數(shù)詳解

    這篇文章主要介紹了C++中的構(gòu)造函數(shù)與析造函數(shù)詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C語言關(guān)于include順序不同導(dǎo)致編譯結(jié)果不同的問題

    C語言關(guān)于include順序不同導(dǎo)致編譯結(jié)果不同的問題

    這篇文章主要介紹了在日常調(diào)試C語言中include的順序不同從而影響最后編譯結(jié)果不同的問題,究其原因是寫代碼的習(xí)慣所導(dǎo)致,下面跟小編一起來看看吧
    2022-04-04
  • C++類和對象實戰(zhàn)之Date類的實現(xiàn)方法

    C++類和對象實戰(zhàn)之Date類的實現(xiàn)方法

    C++ 標(biāo)準(zhǔn)庫沒有提供所謂的日期類型,C++ 繼承了C語言用于日期和時間操作的結(jié)構(gòu)和函數(shù),這篇文章主要給大家介紹了C++類和對象實戰(zhàn)之Date類的實現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • 如何用C語言、Python實現(xiàn)棧及典型應(yīng)用

    如何用C語言、Python實現(xiàn)棧及典型應(yīng)用

    本文先通過實例分別介紹了如何用C語言、Python實現(xiàn)棧,后又介紹棧的典型應(yīng)用,對大家學(xué)習(xí)棧很有借鑒參考價值,下面一起來看看吧。
    2016-08-08
  • C++重載運算符的規(guī)則詳解

    C++重載運算符的規(guī)則詳解

    運算符重載函數(shù)可以是類的成員函數(shù),也可以是類的友元函數(shù),還可以是既非類的成員函數(shù)也不是友元函數(shù)的普通函數(shù)
    2013-10-10
  • C語言楊氏矩陣實例教你編寫

    C語言楊氏矩陣實例教你編寫

    楊氏矩陣是一個數(shù)字矩陣,矩陣的每一行從左到右一次遞增,矩陣從上到下遞增,在這樣的矩陣中查找一個數(shù)字是否存在。時間復(fù)雜度小于O(N),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2023-02-02
  • C語言常見的指針筆試題解析

    C語言常見的指針筆試題解析

    在我們學(xué)習(xí)指針之后,應(yīng)該在實際應(yīng)用中去理解和掌握它,畢竟實踐才是檢驗真理的唯一標(biāo)準(zhǔn),我們以后在找工作的過程中免不了會遇到與指針相關(guān)的試題,本篇文章可以幫助我們提前了解一些常見的指針考點,需要的可以了解一下
    2022-10-10
  • C++多態(tài)實現(xiàn)方式詳情

    C++多態(tài)實現(xiàn)方式詳情

    這篇文章主要介紹了C++多態(tài)實現(xiàn)方式詳情,多態(tài)是一種面向?qū)ο蟮脑O(shè)計思路,本身和C++不是強綁定的,其他語言當(dāng)中一樣有多態(tài),只不過實現(xiàn)的方式可能有所不同。下面來一起了解更多詳細內(nèi)容吧
    2022-01-01
  • 利用C++求絕對值的幾種方法例子

    利用C++求絕對值的幾種方法例子

    相信大家在學(xué)習(xí)C++時,應(yīng)該都有做過求絕對值的題目,下面這篇文章主要給大家介紹了關(guān)于利用C++求絕對值的幾種方法例子,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04

最新評論

鄂温| 水城县| 九龙城区| 阳春市| 荣成市| 南开区| 泗水县| 庄浪县| 巨野县| 巴楚县| 行唐县| 兴安盟| 海安县| 英吉沙县| 江阴市| 长汀县| 唐海县| 子长县| 洛扎县| 加查县| 福鼎市| 怀仁县| 万盛区| 沾化县| 滁州市| 洛阳市| 唐河县| 鄂尔多斯市| 东丽区| 稻城县| 曲阜市| 肥城市| 仪陇县| 博白县| 调兵山市| 观塘区| 嘉黎县| 吉安市| 海晏县| 余江县| 林甸县|