{"id":15769551,"url":"https://github.com/nobodyxu/return-exception","last_synced_at":"2025-03-31T11:22:13.853Z","repository":{"id":109425012,"uuid":"276075673","full_name":"NobodyXu/return-exception","owner":"NobodyXu","description":"Return errors in an unignorable way like exceptions, but with -fno-exceptions support.","archived":false,"fork":false,"pushed_at":"2020-07-23T09:46:27.000Z","size":510,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T02:17:39.369Z","etag":null,"topics":["cpp","error-handling"],"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/NobodyXu.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-30T11:06:57.000Z","updated_at":"2020-07-23T09:46:01.000Z","dependencies_parsed_at":"2023-03-14T14:30:44.255Z","dependency_job_id":null,"html_url":"https://github.com/NobodyXu/return-exception","commit_stats":{"total_commits":97,"total_committers":1,"mean_commits":97.0,"dds":0.0,"last_synced_commit":"478137587d44763ed16f3e71bf6cf1762d10a91f"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobodyXu%2Freturn-exception","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobodyXu%2Freturn-exception/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobodyXu%2Freturn-exception/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobodyXu%2Freturn-exception/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NobodyXu","download_url":"https://codeload.github.com/NobodyXu/return-exception/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246458363,"owners_count":20780742,"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":["cpp","error-handling"],"created_at":"2024-10-04T14:03:19.050Z","updated_at":"2025-03-31T11:22:13.813Z","avatar_url":"https://github.com/NobodyXu.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# return-exception\n\nReturn errors in an unignorable way and have compile-time only Catch, which produces no bloat code with `CXXFLAGS=-O2 -Wl,--strip-all`.\n\n[Document]\n\n## Advantage compared to C++ exception\n\n - Pay for what you use -- only when you use a specific feature will that code be generated.\n - No rtti is required -- `variant` is used for minimal runtime check per-`Ret_except`, only generate\n when required and will not add a lot of global information.\n - You can use any `variant` implementation in `Ret_except`, giving you further control of the \n generated code.\n - All generated code will undergo optimizer, which can heavily optimize to remove any bloat code with \n `CXXFLAGS=-O2 -Wl,--strip-all`.\n - More explicit syntax: `Ret_except` requires all possible exception type to be provided at compile-time.\n - If you don't handle the exception stored in `Ret_except`, then it will terminate your program by\n   - Calling `errx` and print `e.what()` (if `e.what()` is valid) if exception is disabled.\n   - Otherwise, throw exception again.\n\n## Downsides compared to C++ exceptions\n\n - Hard or impossible to use in constructor.\n - Since all possible exception type is explicit, it poses a big problem in template code:\n \u003cbr\u003eYou would have to use detect return type of function and use `glue_ret_except_from_t` to add more\n exceptions.\n\nFor more information, check [Document].\n\n## Usage\n\n```c++\n#include \"/path/to/ret-exception.hpp\"\n\n#include \u003climits\u003e\n#include \u003cstdexcept\u003e\n\n#include \u003ccstdio\u003e\n#include \u003ccstdint\u003e\n#include \u003ccinttypes\u003e\n\n#include \u003cerr.h\u003e\n\ntemplate \u003cclass T\u003e\nauto ftoi(long double f) noexcept -\u003e Ret_except\u003cT, std::invalid_argument, std::out_of_range\u003e\n{\n    if (f == std::numeric_limits\u003cfloat\u003e::infinity())\n        return {std::invalid_argument{\"f should not be INF\"}};\n    else if (f \u003e std::numeric_limits\u003cT\u003e::max())\n        return {std::out_of_range(\"f is too large\")};\n    else if (f \u003c std::numeric_limits\u003cT\u003e::min())\n        return {std::out_of_range(\"f is too small\")};\n    return static_cast\u003cT\u003e(f);\n}\n\nint main(int argc, char* argv[])\n{\n    long double f;\n    std::scanf(\"%Lf\", \u0026f);\n\n    auto integer = ftoi\u003cstd::uint64_t\u003e(f)\n        .Catch([](const std::out_of_range \u0026e) noexcept {\n            // Catch out_of_range only\n            errx(1, \"std::out_of_range: %s\", e.what());\n        }).Catch([](const auto \u0026e) noexcept {\n            // Catch any exception\n            errx(1, \"In function %s: Catched exception %s\", \n                    __PRETTY_FUNCTION__, e.what());\n        }).get_return_value(); /* Get return value here when all exceptions are handled */\n\n    std::printf(\"%\" PRIu64 \"\\n\", integer);\n    return 0;\n}\n```\n\nNow, if you compile the code with `clang++ -std=c++17 -O2 -Wl,--strip-all -fno-exceptions -fno-rtti example.cc`,\nyou will get an executable that is fairly small (on my x86-64 intel machine, 12K only).\n\nLet's do some test on the code:\n\n```\n$ ./a.out\n1.2333\n1\n$ ./a.out\n123412434324823878712471230712847312844\na.out: std::out_of_range: f is too large\n$ ./a.out\nINF\na.out: In function auto main(int, char **)::(anonymous class)::operator()(const auto \u0026) const [e:auto = std::invali\nd_argument]: Catched exception f should not be INF\n```\n\nIt's doing exactly what we want it to do.\n\nWhat is more amazing is that how small the executable can be.\nIf you run the compiler again with \n`clang++ -std=c++17 -O3 -flto -Wl,--strip-all -fno-exceptions -fno-rtti example.cc`, you would probably find\nthe executable to be even smaller.\n\nOn my machine, I found it to be merely 8.9K, which definitely is not possible with c++ exceptions.\n\nFor more information, check [Document].\n\n[Document]: https://nobodyxu.github.io/return-exception/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnobodyxu%2Freturn-exception","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnobodyxu%2Freturn-exception","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnobodyxu%2Freturn-exception/lists"}