{"id":19157772,"url":"https://github.com/coyorkdow/result","last_synced_at":"2025-05-07T08:34:27.029Z","repository":{"id":190840191,"uuid":"683452922","full_name":"coyorkdow/result","owner":"coyorkdow","description":"rust style error handling for cpp","archived":false,"fork":false,"pushed_at":"2023-08-28T15:51:31.000Z","size":22,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-19T20:53:29.350Z","etag":null,"topics":["algebraic-data-types","cpp","error-handling","functional-programming","monad","pattern-matching","rust"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coyorkdow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-26T16:12:21.000Z","updated_at":"2024-11-21T20:49:08.000Z","dependencies_parsed_at":"2023-08-26T17:28:24.468Z","dependency_job_id":"ce00eb5f-a79a-4e43-819c-7b0f5bc5d45d","html_url":"https://github.com/coyorkdow/result","commit_stats":{"total_commits":9,"total_committers":2,"mean_commits":4.5,"dds":0.2222222222222222,"last_synced_commit":"ab9c112a3df95f03d12bae5abf17e5986fae39c1"},"previous_names":["coyorkdow/result"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coyorkdow%2Fresult","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coyorkdow%2Fresult/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coyorkdow%2Fresult/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coyorkdow%2Fresult/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coyorkdow","download_url":"https://codeload.github.com/coyorkdow/result/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252843321,"owners_count":21812859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algebraic-data-types","cpp","error-handling","functional-programming","monad","pattern-matching","rust"],"created_at":"2024-11-09T08:42:02.963Z","updated_at":"2025-05-07T08:34:27.006Z","avatar_url":"https://github.com/coyorkdow.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# result\nRust style error handling for cpp. It provides `result::Result` which supports pattern matching error handling and monadic operation.\n\ncpp17 required\n\n## Basic Usage\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003climits\u003e\n\n#include \"result.hpp\"\nusing result::Result;\n\n// define a Result of int64, which error type is int\nResult\u003cint64_t, int\u003e Multiply(int64_t a, int64_t b) {\n    int64_t res = a * b;\n    if (a != 0 \u0026\u0026 res / a != b) {\n        return {result::Err{}, -1}; // return error\n    }\n    return res; // return result\n}\n\nint main() {\n    // do pattern matching\n    auto v = Multiply(1000, 1000).match(\n        result::Ok()  = [](int64_t v) { return v; },\n        result::Err() = [](int err) { std::cerr \u003c\u003c \"arithmetic overflow\\n\"; return err; }\n    );\n    std::cout \u003c\u003c v \u003c\u003c '\\n';\n    v = Multiply(std::numeric_limits\u003cint64_t\u003e::max(), 1000).match(\n        result::Ok()  = [](int64_t v) { return v; },\n        result::Err() = [](int err) { std::cerr \u003c\u003c \"arithmetic overflow\\n\"; return err; }\n    );\n    std::cout \u003c\u003c v \u003c\u003c '\\n';\n}\n```\n\nthe return type of `result::Result::match` can be automatically deduced through the return type of the pattern handler. \n\nThe output will be\n```\n1000000\narithmetic overflow\n-1\n```\n\n## Using result::Error\n\n`result::Error` is an type that designed to receive any type of the error. By using pattern matching it's easy to determine what kind of error that exactly is.\n\nFirst, let's define a function template that returns `Result\u003cT, result::Error\u003e`\n```cpp\ntemplate \u003cclass T\u003e\nResult\u003cT, result::Error\u003e ElementaryArithmeticFromZeroToMillion(char op, T x, T y) {\n  const T million = 1'000'000;\n  if (!(x \u003e= 0 \u0026\u0026 x \u003c= million) || !(y \u003e= 0 \u0026\u0026 y \u003c= million)) {\n    return {result::Err{}, result::OutOfRangeError{}};\n  }\n  using res_t = Result\u003cT, result::Error\u003e;\n  T res{};\n  switch (op) {\n    case '+':\n      res = x + y;\n      return (res \u003e= 0 \u0026\u0026 res \u003c= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};\n    case '-':\n      res = x - y;\n      return (res \u003e= 0 \u0026\u0026 res \u003c= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};\n    case '*':\n      res = x * y;\n      return (res \u003e= 0 \u0026\u0026 res \u003c= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};\n    case '/':\n      if (y == 0) {\n        return {result::Err{}, result::DivideByZeroError{}};\n      }\n      res = x / y;\n      return (res \u003e= 0 \u0026\u0026 res \u003c= million) ? res_t{res} : res_t{result::Err{}, result::RangeError{}};\n    default:\n      return {result::Err{}, result::InvalidArgumentError{}};\n  }\n}\n```\n\n```cpp\nauto v1 = ElementaryArithmeticFromZeroToMillion('+', 4, 3).match(\n        result::Ok()  = [](int v) { return v; },\n        result::Err() = [](result::Error\u0026\u0026) { return 0; });\nstd::cout \u003c\u003c v1 \u003c\u003c '\\n'; // 7\n\nauto v2 = ElementaryArithmeticFromZeroToMillion('-', 1.5, 10.5).match(\n        result::Ok() = [](double v) { return v; },\n        result::Err() =\n            [](result::OutOfRangeError) {\n              std::cout \u003c\u003c \"the arguments of calculating v2 out of range\\n\";\n              return -1;\n            },\n        result::Err() = /* match here */\n            [](result::RangeError) {\n              std::cout \u003c\u003c \"the result of calculating v2 out of range\\n\";\n              return -2;\n            },\n        result::Err() = /* the default error pattern. must be contained otherwise compile error */\n            [](result::Error\u0026\u0026) {\n              std::cout \u003c\u003c \"unknown error\\n\";\n              return -3;\n            });\nstd::cout \u003c\u003c v2 \u003c\u003c '\\n'; // -2\n```\n\n`result::Error` itself also supports pattern matching.\n\n```cpp\nauto res = ElementaryArithmeticFromZeroToMillion('^', 1, 0);\nres.error().match(\n    [](result::OutOfRangeError) {\n      std::cout \u003c\u003c \"the arguments out of range\\n\";\n      return 0;\n    },\n    [](result::InvalidArgumentError) { /* match here */\n      std::cout \u003c\u003c \"the arguments are invalid\\n\";\n      return 0;\n    },\n    [](result::Error) {\n      std::cout \u003c\u003c \"unknown error\\n\";\n      return 0;\n    });\n```\n\n## Monadic operation\n\n```cpp\nauto res = ElementaryArithmeticFromZeroToMillion('^', 1, 0);\nauto v3 = res.or_else([](const result::Error\u0026) {\n                std::cout \u003c\u003c \"op ^ failed, change to op /\\n\";\n                return ElementaryArithmeticFromZeroToMillion('/', 1, 0);\n              })\n              .and_then([](int v) {\n                std::cout \u003c\u003c \"op / succeed\\n\";\n                return Result\u003cint, result::Error\u003e{v};\n              })\n              .or_else([](const result::Error\u0026) {\n                std::cout \u003c\u003c \"op / failed, change to op +\\n\";\n                return ElementaryArithmeticFromZeroToMillion('+', 1, 0);\n              })\n              .and_then([](int v) {\n                std::cout \u003c\u003c \"op + succeed, time the result by 10\\n\";\n                return ElementaryArithmeticFromZeroToMillion('*', v, 10);\n              })\n              .or_else([](const result::Error\u0026) {\n                std::cout \u003c\u003c \"eventually failed, set value as -1\\n\";\n                return Result\u003cint, result::Error\u003e{-1};\n              })\n              .value();\nstd::cout \u003c\u003c \"the final reuslt is \" \u003c\u003c v3 \u003c\u003c '\\n';\n```\n\nThe output will be\n```\nop ^ failed, change to op /\nop / failed, change to op +\nop + succeed, time the result by 10\nthe final reuslt is 10\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoyorkdow%2Fresult","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoyorkdow%2Fresult","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoyorkdow%2Fresult/lists"}