{"id":26053314,"url":"https://github.com/rvarago/cpp_refined","last_synced_at":"2025-09-12T18:17:09.625Z","repository":{"id":280656513,"uuid":"942584703","full_name":"rvarago/cpp_refined","owner":"rvarago","description":"*EXPERIMENTAL* Types + Predicates in C++, sort-of","archived":false,"fork":false,"pushed_at":"2025-04-21T11:20:43.000Z","size":35,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-21T11:36:38.678Z","etag":null,"topics":["cpp","cpp20-library","refinement-types","type-driven-development"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rvarago.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,"zenodo":null}},"created_at":"2025-03-04T10:37:58.000Z","updated_at":"2025-04-21T10:51:36.000Z","dependencies_parsed_at":"2025-04-21T11:40:46.048Z","dependency_job_id":null,"html_url":"https://github.com/rvarago/cpp_refined","commit_stats":null,"previous_names":["rvarago/cpp_refined"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rvarago/cpp_refined","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvarago%2Fcpp_refined","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvarago%2Fcpp_refined/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvarago%2Fcpp_refined/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvarago%2Fcpp_refined/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rvarago","download_url":"https://codeload.github.com/rvarago/cpp_refined/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rvarago%2Fcpp_refined/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274852555,"owners_count":25361833,"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","status":"online","status_checked_at":"2025-09-12T02:00:09.324Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","cpp20-library","refinement-types","type-driven-development"],"created_at":"2025-03-08T07:27:55.229Z","updated_at":"2025-09-12T18:17:09.613Z","avatar_url":"https://github.com/rvarago.png","language":"C++","readme":"# cpp_refined\n\n\u003e Types + Predicates in C++, sort-of\n\nA Refinement Type constrains a ground type with a predicate, such that we can only produce valid instances (according to the predicate) of the ground type. This is often a language-level feature that comes with a type system that can ergonomically express relationships, e.g. subtyping, flow. [LiquidHaskell](https://ucsd-progsys.github.io/liquidhaskell/) is an example\n\nC++ does not have Refinement Types, so this library is a clumsy attempt to bring some of their benefits to the community.\n\n## Motivation\n\nLet's say that throughout our application we have functions that require integers that are **even** and **less than 10**.\n\nWe could model this as an `int` and whenever we need it to be even we would validate it with \"is_even\" and make a decision based on the result. However, we risk duplicating the same validation step in different functions or, worse, we may forget to validate by mistakenly assuming it has already been validated.\n\nInstead of just validating and immediately forgetting, we can record this validation in the types and use it as \"proof\" that we already validated. So we have _some_ assurance that our precondition has already been checked and therefore we don't need to check again.\n\nAdditionally, this has a nice second-order effect of pushing validation to the edges of our application. As opposed to weakening our postcondition (this function might fail due to invalid arguments checked in the implementation), we strengthen our precondition (accepting only valid arguments) and get rid of this error case altogether.\n\n\u003e Check out [\"Parse, don't validate\"](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) for a more thorough discussion.\n\n## Example\n\n```cpp\n// a refinement for all x of type int such that x is even.\nusing even =\n      rvarago::refined::refinement\u003cint, [](auto const x) { return x % 2 == 0; }\u003e;\n\n// refinements can be further refined, e.g. all x of type such that x is even **and x \u003c 10**.\nusing even_lt_10 =\n      rvarago::refined::refinement\u003cint, [](auto const x) { return x \u003c 10; }, even\u003e;\n\nauto do_something_else(even v) -\u003e void {\n  // deep down in the call stack do we access even's ground type.\n  int const x = v.value();\n  // act on the ground type (int) as we see fit. \n}\n\nauto do_something(even_lt_10 v) -\u003e void {\n  do_something_else(v);\n}\n\nint main() {\n  int const x = read_int();\n  \n  // the default error policy gives an std::optional back.\n  if (std::optional\u003ceven_lt_10\u003e e = even_lt_10::make(x); e) {\n    do_something(*e);\n  }\n  \n  return 0;\n}\n```\n\nWith this example, we notice that not all functions need access to the underlying `int` element and operate entirely on `even_lt_10` or its \"super-type\" `even`. So we validate and convert the `int` element into `even_lt_10` at the very beginning and only fall back to `int` at the very last moment, when we actually need it. Both operations should ideally at the edges of our applications.\n\nAlthough we reported errors via `std::optional` in the example, we can customise it, e.g. to throw an exception with the built-in `even::make\u003crefined::error::to_exception\u003e` or define a whole user-provided policy.\n\nFurthermore, with `rvarago::refined::traits` we can extend a refinement with properties, such as ordered with the spaceship operator.\n\n## Requirements\n\nC++20\n\n## Usage\n\nThis is a header-only library. See [`refined.hpp`](include/rvarago/refined.hpp).\n\n## Contributing\n\nThis repository has a [`flake.nix`](./flake.nix) with everything I need for development/CI (toolchain, language server, etc).\n\nFurthermore, with:\n\n```sh\nnix develop -c check\n```\n\nYou run all CI checks locally.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frvarago%2Fcpp_refined","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frvarago%2Fcpp_refined","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frvarago%2Fcpp_refined/lists"}