C++11 error_code & error_condition.

在C语言中处理错误,用枚举,然后调用完后,检测返回值;

enum errors
{
    SUCCESS = 0,
    NOTFOUND,
};
int openFile(const char *filename, int *pfd) {
    int fd = open(filename, , O_RDONLY);
    if (fd == -1) return NOTFOUND;
    *pfd = fd;
    return SUCCESS;
}

这样,各个不同错误的枚举可能冲突;

而在C++11中,用异常表示错误:

int openFile(const char *filename) {
    int fd = open(filename, , O_RDONLY);
    if (fd == -1) 
        throw std::exception("File not fould");
    return fd;
}

C++11中,从 boost引入了error_code

int openFile(const char *filename, std::error_code &ec) {
    int fd = open(filename, , O_RDONLY);
    if (fd == -1) 
        ec = std::error_code(errno, std::system_category());
    return fd;
}
std::error_code ec;
int fd = openFile(filePath, ec);
if (ec) {
    std::cout << "Category: " << ec.category().name()
              << "Value: " << ec.value() << '\n'
          << "Message: " << ec.message() << '\n';
}

每个分类,有自己的error_code,这样就避免了枚举冲突;同时也引入了error_condition;

  • error_code 基本上是比較底層的錯誤碼,針對有可能會因為作業系統實作的不同
  • error_condition 則是和平台差異無關(platform-independent)的錯誤碼,主要是用來做比較用的

而兩者也是可以拿來做比較的,不過 error_code 和 error_code 比較時,是確認是否完全相同;但是拿 error_code 和 error_condition 必較的時候,則是確認兩者是否「等價」,這部分算是比較不一樣的地方。

C++17:

std::error_code ec;
std::filesystem::copy_file("aaa", "bbb", ec);
if (ec)
  std::cout << ec << "\n" << ec.message() << std::endl;

在 Windows 平台上,錯誤會是:

system:80
檔案存在。

但是在 Linux 環境的話,他的錯誤會是:

generic:17
File exists

可以看到,雖然這邊是同樣一個錯誤狀況,但是因為平台的不同,所以拿到的 error_code 不管是 error_category 或是錯誤代碼,都是不一樣的。

而和平台差異性無關的 error_condition 就是為了解決這個問題而設計的。

int fd = openFile(filePath, ec);
std::error_condition cond1(1, std::system_category());
std::error_condition cond2(2, std::system_category());
if (ec == cond1) {
}
else if (ec == cond2) {
}
else {
}

定义自己的error_code 需要的函数:

std::is_error_code_enum

 

std::error_code

定义于头文件 <system_error>

template< class T >
struct is_error_code_enum;

(C++11 起)

T 是错误码枚举,则此模板提供等于 true 的成员常量 value 。对于任何其他类型, value 为 false 。

此模板可以为用户定义类型特化,以指示该类型适合于 std::error_codestd::error_condition 自动转换。

std::is_error_code_enum 鉴别枚举是否可作为 std::error_condition,若 T 是错误码枚举,则此模板提供等于 true 的成员常量 value 。对于任何其他类型, value 为 false 。
此模板可以为用户定义类型特化,以指示该类型适合于 std::error_code 及 std::error_condition 自动转换。

#include <iostream>
using namespace std;
#include <system_error>
#include <cassert>

namespace mylib
{
    namespace errc {

        enum my_error
        {
            failed = 0
        };

        inline const char* error_message(int c)
        {
            static const char* err_msg[] =
            {
                "Failed",
            };

            assert(c < sizeof(err_msg) / sizeof(err_msg[0]));
            return err_msg[c];
        }

        class my_error_category : public std::error_category
        {
        public:

            my_error_category()
            { }

            std::string message(int c) const
            {
                return error_message(c);
            }

            const char* name() const noexcept { return "My Error Category"; }

            const static error_category& get()
            {
                const static my_error_category category_const;
                return category_const;
            }
        };

        inline std::error_code make_error_code(my_error e)
        {
            return std::error_code(static_cast<int>(e), my_error_category::get());
        }

    } // end namespace errc
} // end namespace mylib

namespace std {

    template<>
    struct is_error_code_enum<mylib::errc::my_error>
        : std::true_type
    { };

} // end namespace std

int main()
{
    std::error_code ec1 = mylib::errc::make_error_code(mylib::errc::failed); // works
 std::error_code ec2 = mylib::errc::failed; // works
 bool result = (ec2 == mylib::errc::failed); // works

    std::cout << ec1 << std::endl;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值