{"id":25406490,"url":"https://github.com/lostincompilation/rangebasedforloop-withcounter","last_synced_at":"2025-06-10T16:11:35.726Z","repository":{"id":159523288,"uuid":"590522678","full_name":"LostInCompilation/RangeBasedForLoop-WithCounter","owner":"LostInCompilation","description":"C++ Range Based For Loops with integer counter/index variable","archived":false,"fork":false,"pushed_at":"2024-06-02T02:12:57.000Z","size":56,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T23:28:45.468Z","etag":null,"topics":["cpp","cpp20","for-loops","header-only","helper","iterator","ranges","stl-containers","utility"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LostInCompilation.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,"zenodo":null}},"created_at":"2023-01-18T15:59:33.000Z","updated_at":"2025-04-02T15:33:30.000Z","dependencies_parsed_at":"2025-04-12T22:56:54.101Z","dependency_job_id":"6aed8320-9aa1-465b-b197-d0e2e595f13c","html_url":"https://github.com/LostInCompilation/RangeBasedForLoop-WithCounter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LostInCompilation%2FRangeBasedForLoop-WithCounter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LostInCompilation%2FRangeBasedForLoop-WithCounter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LostInCompilation%2FRangeBasedForLoop-WithCounter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LostInCompilation%2FRangeBasedForLoop-WithCounter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LostInCompilation","download_url":"https://codeload.github.com/LostInCompilation/RangeBasedForLoop-WithCounter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LostInCompilation%2FRangeBasedForLoop-WithCounter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259106728,"owners_count":22805941,"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","cpp20","for-loops","header-only","helper","iterator","ranges","stl-containers","utility"],"created_at":"2025-02-16T05:32:45.233Z","updated_at":"2025-06-10T16:11:35.430Z","avatar_url":"https://github.com/LostInCompilation.png","language":"C++","readme":"# Range-Based For Loop with counter variable\n\n![Platform](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS%20%7C%20anything%20else-blue?style=flat-square\u0026\u0026logo=Platform.sh) ![Version](https://img.shields.io/badge/Version-V1.1-brightgreen?style=flat-square\u0026) ![CPP](https://img.shields.io/badge/Language-C++20-orange?style=flat-square\u0026\u0026logo=C%2b%2b)\n\n###### ⚠️ README will be updated for the new version soon.\n\n##### Small single header utility to add an integer counter/index variable to C++ Range-Based For Loops. Full cross platform support.\n\n## Contents\n- [Simple example](#simple-example)\n- [Description](#description)\n    - [Motivation](#motivation)\n    - [Supported container types](#supported-container-types)\n- [Usage](#usage)\n    - [Installation](#installation)\n    - [Basic usage](#basic-usage)\n        - [STL Container](#stl-container)\n        - [Associative containers like `std::map`](#associative-containers-like-stdmap)\n        - [Iterators](#iterators)\n        - [C-Style Arrays](#c-style-arrays)\n        - [r-Values](#r-values)\n        - [Initializer list](#initializer-list)\n    - [Using an offset for index](#using-an-offset-for-index)\n    - [Reverse](#reverse)\n        - [Reverse index](#reverse-index)\n        - [Reverse elements](#reverse-elements)\n- [Count-function overview](#count-function-overview)\n    - [Parameters](#parameters)\n    - [Return type and variable types](#return-type-and-variable-types)\n    - [Overloads](#overloads)\n\n*See also: [License (zlib)](LICENSE.md)*\n\n## Simple example\n```cpp\nstd::vector\u003cstd::string\u003e vec = {\"Element 1\", \"Element 2\", \"Element 3\"};\n\nfor(auto [value, index] : count(vec))\n    std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl; // Index will be incremented automatically\n```\n\nWhere `value` is of type `std::string\u0026`, and `index` is of type `const std::iterator_traits\u003cstd::vector\u003cstd::string\u003e::iterator\u003e::difference_type\u0026`, which can be implicitly cast to an `int`.\n\n##### Console output:\n```\n0: Element 1\n1: Element 2\n2: Element 3\n```\n\n## Description\nWith this small header utility you can easily add an index variable to Range Based For Loops, without any verbose code.\nYou can use any STL-Container, `std::initializer_list` or custom types derived from them. l-Values and r-Values are both supported.\nAdditionally you can specify a **counter offset**, to start counting at a different value than zero (see [Using an offset](#using-an-offset-for-index)).\n**Reverse counting** is also supported in two different variants. Reversing the enumeration of the elements itself (start with last element in container) or just reverse the index variable (start index at number of elements in container and count down to zero). Both modes can be combined (see [Reverse](#reverse)).\n\n### Motivation\nWhile declaring a separate counter variable right above the Range Based For Loop would work, it adds quite some verbosity to the code. Also the counter variable's scope would be valid outside of the loop too, which can lead to some nasty name clashes.\nWith C++20 we got initialization in Range Based For Loops, but this also adds verbosity to the code by declaring a separate variable and incrementing it:\n```cpp\nfor (int index = 0; auto\u0026 value : vec)\n    i++; // Increment still needed\n```\n\nThe above example can also introduce some nasty lifetime issues with more complex types, since Range Based For Loops destroy any temporaries before actually running.\n\nI wanted to make a simple and universal solution, with almost no verbosity and the flexibility to count up or down and start counting based on an offset.\n\n### Supported container types\nType | Container | Supported |\n| -- | --------- | --------- |\n| C-Style Array | `int myArr[42];` | ✅ Yes |\n| Sequence | `std::array` \u003cbr\u003e `std::vector` \u003cbr\u003e `std::deque` \u003cbr\u003e `std::forward_list` \u003cbr\u003e `std::list` | ✅ Yes |\n| Associative | `std::set` \u003cbr\u003e `std::map` \u003cbr\u003e `std::multiset` \u003cbr\u003e `std::multimap` \u003cbr\u003e `std::unordered_set` \u003cbr\u003e `std::unordered_map` \u003cbr\u003e `std::unordered_multiset` \u003cbr\u003e `std::unordered_multimap` | ✅ Yes |\n| Adaptors | `std::stack` \u003cbr\u003e `std::queue` \u003cbr\u003e `std::priority_queue` \u003cbr\u003e `std::flat_set` \u003cbr\u003e `std::flat_map` \u003cbr\u003e `std::flat_multiset` \u003cbr\u003e `std::flat_multimap`| ❌ No\u003cbr\u003eThese types aren't iterable and don't support Range Based For Loops[^1] |\n| Special | `std::initializer_list` \u003cbr\u003e `std::iterator` | ✅ Yes |\n\n[^1]: You can use a workaround and copy, for example, a `std::queue` into a temporary `std::vector` which then can be used with the `count(...)` function. But this introduces run time overhead.\n\n## Usage\n\n### Installation\nInclude the `RangeForLoopWithCounter.h` header and use the `RBFLCounter` namespace and you're good to go. Requires **C++20**.\n\n```cpp\n#include \"RangeForLoopWithCounter.h\"\n\nusing namespace RBFLCounter;\n```\n\n### Basic usage\nSimply use the `count(...)` or `rcount(...)` (reverse count) function for everything. See [the documentation of the count/rcount function](#count-function-overview) down below for further info.\n\n- #### STL Container\n    Usage with STL-Containers is straightforward:\n    ```cpp\n    std::vector\u003cstd::string\u003e vec = {\"Element 1\", \"Element 2\", \"Element 3\"};\n\n    for(auto [value, index] : count(vec))\n        std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n    ```\n\n- #### Associative containers like `std::map`\n    ⚠️ Supported. README will be updated soon.\n\n- #### Iterators\n    You can also use `std::iterator` to specify a range. This will print  only the first two elements of `vec`.\n    ```cpp\n    for(auto [value, index] : count(vec.begin(), vec.begin() + 2))\n        std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n    ```\n\n- #### C-Style Arrays\n    C-Style arrays can be used in the same way:\n    ```cpp\n    int arr[] = {42, 43, 44, 45, 46, 47};\n    \n    for(auto [value, index] : count(arr))\n        std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n    ```\n\n- #### r-Values\n    The `count` and `rcount` functions fully support r-Values and move semantics. However due to the design of Range Based For Loops in C++ (they destroy every temporary before actually running), `count` and `rcount` must become an *owning view* for r-Values. This means that what ever r-Value you pass to `count` or `rcount` will be copied inside of it.\n    ```cpp\n    for(auto [value, index] : count(std::vector\u003cstd::string\u003e{\"X\", \"Y\", \"Z\"}))\n        std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n    ```\n\n- #### Initializer list\n    An `std::initializer_list` can also be used (l-Values and r-Values):\n    ```cpp\n    for(auto [value, index] : count({\"L1\", \"L2\", \"L3\"}))\n        std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n    ```\n    \n### Using an offset for index\nTo use an offset for the counter variable, simply pass an offset to the \n`count(Container, Offset=0)` or `rcount(Container, Offset=0)` function:\n\n```cpp\nstd::vector\u003cstd::string\u003e vec = {\"Element 1\", \"Element 2\", \"Element 3\"};\n\nfor(auto [value, index] : count(vec, 42)) // Start counting at 42\n    std::cout \u003c\u003c index \u003c\u003c \": \" \u003c\u003c value \u003c\u003c std::endl;\n```\n\nThe default offset value is zero.\n\n##### Console output:\n```\n42: Element 1\n43: Element 2\n44: Element 3\n```\n\n### Reverse\nThere are two different types of reversing, which can also be combined:\n\n- #### Reverse index\n    index\n- #### Reverse elements\n    elements\n\nTo combine both modes, use `rcount` with the last parameter (reverse index) set to true.\n\n## Count function overview\nThe `count` and `rcount` functions provide different overloads and parameters for usage with different types and to adjust the behaviour of the counting.\nThe `count` and `rcount` functions are `constexpr`.\n\n### Parameters\nThe general usage is `count(Container, Offset=0, ReverseIndex=false)` and `rcount(Container, Offset=0, ReverseIndex=false)`:\n- `Container` is any type of container or array.\n- `Offset` is the offset from where to start counting. Default is zero.\n- `ReverseIndex` is a boolean to enable counting in reverse for the index (start at number of elements in container, counting down to zero). Default is false (no reverse index counting).\n\n### Return type and variable types\nreturn\n\n### Overloads\n\n- C-Style arrays\n    ```cpp\n    template\u003ctypename T, std::size_t size\u003e\n    count(T (\u0026arr)[size], const std::ptrdiff_t\u0026 offset = 0)\n    ```\n\n- Iterators\n    ```cpp\n    template\u003ctypename IteratorType\u003e\n    count(const IteratorType\u0026 first, const IteratorType\u0026 last, const typename std::iterator_traits\u003cIteratorType\u003e::difference_type\u0026 offset = 0)\n    ```\n\n    Note: There is no `rcount` function for iterators, since you can just pass a reverse iterator to the normal `count` function, which then behaves like `rcount`: `std::rbegin(...)` and `std::rend(...)`.\n\n- l-Value container and l-Value `std::initializer_list`\n    ```cpp\n    template\u003ctypename ContainerType\u003e\n    count(ContainerType\u0026 container, const typename std::iterator_traits\u003ctypename ContainerType::iterator\u003e::difference_type\u0026 offset = 0)\n    ```\n\n- r-Value container\n    ```cpp\n    template\u003ctypename ContainerType\u003e\n    count(ContainerType\u0026\u0026 container, const typename std::iterator_traits\u003ctypename ContainerType::iterator\u003e::difference_type\u0026 offset = 0)\n    ```\n\n- r-Value `std::initializer_list`\n    ```cpp\n    template\u003ctypename T\u003e\n    count(std::initializer_list\u003cT\u003e\u0026\u0026 init_list, const std::ptrdiff_t\u0026 offset = 0)\n    ```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flostincompilation%2Frangebasedforloop-withcounter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flostincompilation%2Frangebasedforloop-withcounter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flostincompilation%2Frangebasedforloop-withcounter/lists"}