c++ - 使用 `std::error_code` 的最佳实践

标签 c++ error-code

我目前正在构建一个嵌入式系统并使用现代 C++ 编译器。
虽然我在技术上可以在给定资源(ARM7,超过 10M RAM)中进行异常处理,但我认为异常不是处理此类事情的正确工具,并且使用异常需要 RTTI,这反过来会导致代码膨胀。
无论如何,为了保持 C++ 风格,我想使用 std::error_code (或类似的更多数据)因为我确实喜欢这个概念。
但是,对于如何实际使用它们似乎没有任何共识。我已经看到至少四种在函数调用之间传递它们的不同方式,其中两种具有多种语义。

  • 通过指针作为参数传递
    void somefunction(Args..., std::error_code* error);
    
    这是我不经常看到的方式,也是我最不喜欢的方式。它使返回类型完全可用并且(通常但不总是)通过 nullptr导致正常的 throw 行为。
  • 通过引用作为参数传递
    void somefunction(Args..., std::error_code& error);
    
    这是我更喜欢的一个。它离开 returnvalue完全可用,并明确指出 error_code不是可选的。
  • 按值返回
    std::error_code somefunction(Ret& out <= if used, Args...);
    
    我经常看到这个,但不是很喜欢它,因为它会耗尽你的返回值,而且我通常不喜欢“输出参数”,除非没有办法绕过它们。
  • 返回 std::variant<Ret, std::error_code>
    std::variant<Ret, std::error_code> somefunction(Args...);
    
    这允许返回值,但使访问值和错误更加困难。此外,它使调用函数的代码更加冗长。

  • 语义
    如果error_code,我已经看到具有不同语义的方式1和2已通过。
  • 启动时清除并设置错误
  • 仅设置错误
  • 如果 error_code 则在开始时立即返回是“设置”

  • 如果您想减少调用代码中的错误检查,最后一种方法非常好。因为你可以通过一个 error_code多个函数之间没有检查,并且第一个错误之后的所有内容都不会执行,类似于异常的执行方式。
    我个人确实更喜欢检查和返回的方式2,但是我可能有偏见。
    有一些推荐/普遍接受的方法吗?

    最佳答案

    好的,这不是完整的答案,实际上也不是完美的主题,因为我不知道执行此操作的标准方法。但是我曾经看到一个漂亮的小技巧,可以让错误代码更难被误用。考虑以下代码:
    结构 MyEC {
    我的EC(){}
    我的EC(我的EC &&其他): parent (&其他){
    //如果未检查其他,则可能记录和或中止
    其他.checked = false;
    }
    //删除其他构造函数和赋值运算符

    〜我的EC(){
    if(!checked && parent == nullptr) {
    //记录和或中止
    }
    }

    [[nodiscard]] std::error_code check() {
    检查=真;
    返回 ec;
    }

    无效集(std::error_code err){
    如果(父 == nullptr) ec = err;
    否则 parent ->设置(错误);
    }
    私有(private)的:
    MyEC* 父级 = nullptr;
    检查=真;
    std::error_code ec {};
    };

    int foo(MyEC&& err) {
    err.set(/* 一些错误 */);
    返回 5;
    }

    int foo1(MyEC&&) {
    返回 4;
    }

    无效酒吧(){
    MyEC 错误;
    富(标准::移动(错误));
    //err 有错误代码,如果没有检查,我们会知道


    foo1(std::move(err));
    //即使没有发生错误,如果没有检查错误,我们也会中止。
    }

    当错误代码未设置但也未检查时,它甚至会中止,这非常好。移动后有很多用处,有点奇怪,不过这里没问题。

    关于c++ - 使用 `std::error_code` 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62611885/

    相关文章:

    c++ - OpenGL GLI 不支持 VS2015?

    C++ 将 char** 分配给字符串数组

    c - 我应该处理哪些错误?哪些是 "fatal"?

    ruby-on-rails - 尝试连接到 Actioncable 服务器时出现 websocket 错误代码 1006

    ios - 无法在设备上运行 Frank 测试,尽管 Frankified 应用程序在设备上

    C++ std::map<std::string, std::set<std::string>> 。如何循环设定值?

    c++ - 没有匹配函数调用 'getline'

    c++ - 12个统治骑士拼图(回溯)

    ruby-on-rails - 如何在rails中为api定义自定义错误代码

    rest - 使用Micronaut进行客户端错误处理