欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

使用expected進(jìn)行錯(cuò)誤處理

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

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

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

下面我會(huì)以一個(gè)例子把第三方庫(kù)中的 expected 庫(kù)的使用方式介紹給大家。

expected 使用實(shí)例

由于該第三方庫(kù)是 head-only 的,所以你只需要進(jìn)到GitHub倉(cāng)庫(kù)把對(duì)應(yīng)的頭文件復(fù)制過(guò)來(lái),便可引入使用。

下面是示例代碼,樣例是 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,因?yàn)槠渲杏玫搅?string_view 以及更智能的自動(dòng)類型推導(dǎo)(如果低于這個(gè)幫會(huì)導(dǎo)致unexpected需要指定明確的error類型)。

函數(shù)式的接口

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

簡(jiǎn)單示例如下:

#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)造了一個(gè)錯(cuò)誤
                         ? 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)造了一個(gè)錯(cuò)誤
                         ? 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實(shí)現(xiàn)優(yōu)雅的錯(cuò)誤處理的文章就介紹到這了,更多相關(guān)C++錯(cuò)誤處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)之鏈?zhǔn)蕉鏄?shù)詳解

    數(shù)據(jù)結(jié)構(gòu)之鏈?zhǔn)蕉鏄?shù)詳解

    所謂二叉樹(shù)遍歷 (Traversal) 是按照某種特定的規(guī)則,依次對(duì)二叉樹(shù)中的節(jié)點(diǎn)進(jìn)行相應(yīng)的操作,并且每個(gè)節(jié)點(diǎn)只操作一次。本文通過(guò)代碼示例詳細(xì)介紹了C語(yǔ)言中的鏈?zhǔn)蕉鏄?shù),需要的朋友可以參考一下
    2023-04-04
  • 淺談C語(yǔ)言中strcpy,strcmp,strlen,strcat函數(shù)原型

    淺談C語(yǔ)言中strcpy,strcmp,strlen,strcat函數(shù)原型

    下面小編就為大家?guī)?lái)一篇淺談C語(yǔ)言中strcpy,strcmp,strlen,strcat函數(shù)原型。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • C字符串操作函數(shù)實(shí)現(xiàn)方法小結(jié)

    C字符串操作函數(shù)實(shí)現(xiàn)方法小結(jié)

    這篇文章主要介紹了C字符串操作函數(shù)實(shí)現(xiàn)方法,實(shí)例總結(jié)了C語(yǔ)言字符串操作的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • C++內(nèi)聯(lián)函數(shù)詳情

    C++內(nèi)聯(lián)函數(shù)詳情

    這篇文章主要介紹了C++內(nèi)聯(lián)函數(shù),文章主要圍繞C++內(nèi)聯(lián)函數(shù)的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,需要的朋友可以參考一下,希望對(duì)大家有所幫助
    2021-11-11
  • C語(yǔ)言詳細(xì)解析有符號(hào)數(shù)與無(wú)符號(hào)數(shù)的表示

    C語(yǔ)言詳細(xì)解析有符號(hào)數(shù)與無(wú)符號(hào)數(shù)的表示

    我們知道,在C語(yǔ)言中存在無(wú)符號(hào)數(shù)和有符號(hào)數(shù),但是對(duì)于計(jì)算機(jī)而言,其本身并不區(qū)別有符號(hào)數(shù)和無(wú)符號(hào)數(shù),因?yàn)樵谟?jì)算機(jī)里面都是O或者1,但是在我們的實(shí)際使用中有時(shí)候需要使用有符號(hào)數(shù)來(lái)表示一個(gè)整數(shù),因此我們規(guī)定,當(dāng)最高位為1的時(shí),表示為負(fù)數(shù),最高位為0時(shí),表示為正數(shù)
    2022-04-04
  • C語(yǔ)言實(shí)現(xiàn)一個(gè)通訊錄

    C語(yǔ)言實(shí)現(xiàn)一個(gè)通訊錄

    這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)一個(gè)通訊錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • C++數(shù)據(jù)結(jié)構(gòu)AVL樹(shù)全面分析

    C++數(shù)據(jù)結(jié)構(gòu)AVL樹(shù)全面分析

    今天的這一篇博客,我要跟大家介紹一顆樹(shù)——AVL樹(shù),它也是一顆二叉搜索樹(shù),它就是在二叉搜索樹(shù)中加了一個(gè)平衡因子的概念在里面,下面我就來(lái)和大家聊一聊這棵樹(shù)是個(gè)怎么樣的樹(shù)
    2021-10-10
  • C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略

    C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略

    這篇文章主要介紹了C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略,Bridge將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化需要的朋友可以參考下
    2016-03-03
  • 在C++中實(shí)現(xiàn)高效的數(shù)組原地輪轉(zhuǎn)的方法總結(jié)

    在C++中實(shí)現(xiàn)高效的數(shù)組原地輪轉(zhuǎn)的方法總結(jié)

    在 C++ 中,可以通過(guò)多種方式實(shí)現(xiàn)數(shù)組的輪轉(zhuǎn)操作,以下是幾種常見(jiàn)的實(shí)現(xiàn)方法及其對(duì)應(yīng)的代碼示例,文中通過(guò)代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2025-04-04
  • C語(yǔ)言實(shí)現(xiàn)24位彩色圖像二值化

    C語(yǔ)言實(shí)現(xiàn)24位彩色圖像二值化

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)24位彩色圖像二值化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評(píng)論