{"id":19462584,"url":"https://github.com/zerodaycode/zero","last_synced_at":"2025-04-25T08:31:18.900Z","repository":{"id":60520587,"uuid":"500422181","full_name":"zerodaycode/Zero","owner":"zerodaycode","description":"Libraries for modern C++","archived":false,"fork":false,"pushed_at":"2024-09-10T16:08:50.000Z","size":83311,"stargazers_count":5,"open_issues_count":5,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-09-10T18:01:56.615Z","etag":null,"topics":["cpp20","cpp20-modules","modern-cpp"],"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/zerodaycode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2022-06-06T12:21:13.000Z","updated_at":"2024-08-15T11:29:53.000Z","dependencies_parsed_at":"2024-04-19T14:50:25.495Z","dependency_job_id":"b42226e3-3b27-4d5a-bddd-273fdd922d56","html_url":"https://github.com/zerodaycode/Zero","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodaycode%2FZero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodaycode%2FZero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodaycode%2FZero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodaycode%2FZero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerodaycode","download_url":"https://codeload.github.com/zerodaycode/Zero/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223992713,"owners_count":17237501,"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":["cpp20","cpp20-modules","modern-cpp"],"created_at":"2024-11-10T18:03:57.244Z","updated_at":"2024-11-10T18:03:58.028Z","avatar_url":"https://github.com/zerodaycode.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The ZERO project\n\nZero project it's a set of powerful libraries written in modern C++ and for\nmodern C++ projects\n\n## Libraries\n\nQuick description, and links to the documentation of all the libraries of the project\n\n- [Physics](./zero/ifc/physics/README.md) - A general purpose library for dealing with field related aspects and problems of physics\n  - [Quantities](./zero/ifc/physics/quantities) - Compile time library for work with physical quantities acording the `SI`\n- [Collections](./zero/ifc/collections/README.md) - Custom containers, operations and interfaces\n- [Iterators](./zero/ifc/iterators/README.md) - Custom iterator interfaces, and some legacy implementation (just as examples) of the legacy ones\n- [Text](./zero/ifc/text/README.md) - Offers utilities for text manipulation, string splitting, formatting, styling, and print to console functionalities.\n- [Types](./zero/ifc/types/README.md) - Information about types and traits for types\n- [Math](./zero/ifc/math/README.md) - Mathematical operations and functions\n- [Test Suite](./zero/ifc/test-suite/README.md)  - A flexible and simple test-suite.\n\n## Sponsorship\n\n\u003cimg src=\"https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg\" width=\"100\" /\u003e\nThis project has been supported directly by JetBrains, giving us free access to all of their amazing products.\nYou guys rocks, thanks! \n\n## Motivation\n\nZero's main ideas and motivations can be summarized in the search for a deeper understanding of the roots of C++ than usual. For that,\nwe are aim to implement library functionalities that we are missing in the language, or that we would like to know how they must be build\nfrom scratch.\nOne way of understand this felling, is thanks to Jason Turner, and it's incredible [C++ Weekly](https://www.youtube.com/playlist?list=PLs3KjaCtOwSZ2tbuV1hx8Xz-rFZTan2J1) YouTube\nchannel. In particular, you can checkout [this particular episode](https://youtu.be/287_oG4CNMc?list=PLs3KjaCtOwSZ2tbuV1hx8Xz-rFZTan2J1\u0026t=378) and immediately\nyou understand our feeling!\n\nAlso, we like to create and share new libraries that are part of our way to see the world. For example, the physics\nlibrary born as an idea of \"what if we could code the Physics degree?\" From the roots, by starting with units and system\nof measurements, until complex equation systems, matrix and problems solver...! As well as a new math library.\nWe are well aware that already exists maths libraries. But this idea is, learn the degree by... coding it!\n\nAnother basis of the project is the use of modules. Many talks and conferences have exposed the goodness and benefits of migrating\nto the new model, but let's be realistic, it is unfeasible to rewrite more than 40 years of projects.\nWhat is feasible, however, is to use the modules in projects that start from scratch, like this one.\n\nZero was born from the idea of improving as library developers, to be able to design better public APIs and to offer content focused on maintainability, sustainability, scalability and performance, and, above all, it is a personal and professional learning project about different software engineering tools, and in search of a deeper knowledge of one of our favorite tools, C++.\n\n## Build system\n\nThe last but not least, is using `Zero` as a platform for showing our [`Zork++`](https://github.com/zerodaycode/Zork) build\nsystem in a real world environment, so people can profit by taking examples of how we set-up things with `Zork++`\nin a big scale project. Also, we introduce the changes of the latest releases available here, so it serves as well as\na kind of latest up-to-date guide.\n\n## General guidelines and API design\n\nThis entry is a collection of both the things that we're looking for, or focusing on\nin the design of our code, or how we with that design, decide to implement the user's\nAPI.\n\n### Design APIs to make it able to be processed at compile-time\n\nWe all know the marvelous `constexpr` C++ keyword. This is, compute the things that you can at\ncompile-time if you are able to do so. `C++20` brings us other alternatives, like `consteval`, which\nmeans work only if you're able to do your computations at compile-time, or `Concepts`, that are template\nconstraints for types.\n\nProcess your data at compile-time has a lot of incredible benefits. It provides faster runtime\napplications, since the job is already done. But, our favourite thing by far, is that working with this\nkind of code make us able to spot any kind of users code errors when the code is being compiled, instead\nof having to produce a failure when their program is running.\n\nLet's take, for example, the `std::get\u003c\u003e()` template. This function takes a template parameter that\nmust be an index or a type, to retrieve an element from a generic collection. Let's say that you have\nand `std::array\u003cint, 3\u003e`, and you want to get the fifth element. As you may be spotted, there's no such\nfifth element, since the array only contains 4 elements! If you tried to retrieve the element with the\n*index subscript operator*, for example `my_array[5]`, you will go directly towards *undefined behaviour*.\nYou will be accessing a memory address outside the arrays range, bring if you thrash data if you're lucky\nenough, because all kind of bad things could have happen.\n\nSo, most of the time, you will face our APIs, that will be asking you for certain template parameters\nthat maybe you weren't expecting. But this has a powerful reason, we are able to provide you an API\nthat is non-throwable, or doesn't lead you to write code that creates *undefined behaviour*.\nAnd sometimes, you'll find mixed behaviour. Take in consideration our `Matrix` type, from the\nlinear-algebra library.\n\n```c++\nMatrix m {\n    std::array{3, 5, 8},\n    std::array{4, 7, 9},\n    std::array{9, 1, 15}\n};\nassertEquals(m[0][0] == 3);\n```\n\nThe `Matrix` type has a constructor based on an `std::initializer_list`. This means that you're able\nto don't have to write the outter array, and just declare the arrays that holds the real matrix data.\nBut that's not the point. The point is the template argument deduction. You instantiated a new matrix,\nwhich is a template class. The template class has two non template parameters, the two first, to specify\nthe number of rows and columns that your matrix has, and the third, which is a template parameter for\nindicate the type of the data that will be holding. This means that the parameters deduced will\nbe, for the example above, `3, 3, int`. This means that, when you want to make a matrix multiplication\noperation with a 3 by 5 matrix, we may check and ensure that the multiplication operation is defined,\nbecause the first matrix matches the same number of columns that the second matrix number of rows, so\nwe can multiply them (otherwise, the multiplication operation isn't defined between the first and the second.)\n\nBut the neat thing is that we can check this at compile time! If you try to multiply two 2 by 3 matrices,\nyou'll see a compile time error, and you can fix it in your codebase, non when the program is running.\nThis is a huge advantage that compile-time programming provides, and we'll try to focus on it make it present\nin all of our APIs whenever is possible.\n\nWe can take also the example of how we provide an API to get an element from the matrix.\n```c++\nMatrix\u003c3, 3, int\u003e m {\n    std::array{3, 5, 8},\n    std::array{4, 7, 9},\n    std::array{9, 1, 15}\n};\n\n// Using the fluent builder API to access elements\nint element = m.row\u003c0\u003e().column\u003c0\u003e(); // Retrieves the element at row 0, column 0 (value: 3)\n```\n\nThe row and column methods are templated, allowing you to specify the row or column index at compile time.\nIf the provided index is out of range, you will get a compile-time error, ensuring that users are accessing valid\nelements of the matrix.\n\nThis fluent builder API improves the safety and usability of the matrix class, providing compile-time checks and\neliminating the possibility of runtime failures when accessing elements.\n\nBut, in this particular case, we are also providing for this API the typical subscript operator `[]`.\nEven we already discussed the benefits of using non failable runtime APIs, not always must be convenient\nto use those one (specially, when prototyping). We prefer to maintain a neutral position most of the time,\nwhere as library designers we just offer both approaches, and its ultimately the developer which decides\nwhat option fits the best in their codebase.\n\n### Prefer to work with value APIs vs reference/pointers APIs\n\n// TODO\n\n### Avoid returning raw pointers from functions\n\n// TODO\n\n### Make the public APIs exception-free\n\nWe largely hate the APIs that throws exceptions to the client code. Throw exceptions\nis typically used in the industry as a way to propagate all kind of errors, and that's\nshouldn't be the way of how exceptions must be used. The word exception already has a strong\nmeaning, that, for us, is *something exceptionally bad happened in the runtime of your program*,\nand you must take care of it.\nExceptions has a high runtime cost, user's must be aware that a certain API is throwable, and then handle properly.\nAt the time of writing, already exists modern alternatives for deal with errors that mustn't be considered\nas any kind of exception, like `std::optional` and *C++23* `std::expected`, so they will be present\nin our codebase as the major guideline to follow when we are working and providing a fallible API.\n\n### Avoid non initialized code\n\nLet's be clear. Non initialized code is ugly, dark and error prone. Also, it has the major drawback that\nif code isn't managed properly, developers can fall into the classical error of work with non initialized\ndata, that will lead them towards *undefined behaviour*.\n\nModern languages are going towards code workflows that avoids non initialized data, or probably are forbidden already\nin the language. Sure that there's situations where you may need to wait for user input, maybe working with streams,\nor another kind of \"justified\" situation, but in general non initialized code must be avoided whenever is possible.\n\nTo help with this situation, you'll see that most of our types has deleted its default constructor, thing\nthat must force the users to better design their code workflows, but in the end, creating a more robust\nand less error prone codebases.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodaycode%2Fzero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerodaycode%2Fzero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodaycode%2Fzero/lists"}