{"id":13424485,"url":"https://github.com/tcbrindle/NanoRange","last_synced_at":"2025-03-15T18:35:09.300Z","repository":{"id":47303095,"uuid":"106315089","full_name":"tcbrindle/NanoRange","owner":"tcbrindle","description":"Range-based goodness for C++17","archived":false,"fork":false,"pushed_at":"2021-02-11T22:22:46.000Z","size":1831,"stargazers_count":361,"open_issues_count":18,"forks_count":27,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-03-15T11:03:42.225Z","etag":null,"topics":["concepts","cplusplus","cplusplus-20","range","ranges-proposal"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tcbrindle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE_1_0.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-09T17:40:27.000Z","updated_at":"2025-03-12T19:29:29.000Z","dependencies_parsed_at":"2022-09-06T14:02:32.063Z","dependency_job_id":null,"html_url":"https://github.com/tcbrindle/NanoRange","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/tcbrindle%2FNanoRange","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcbrindle%2FNanoRange/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcbrindle%2FNanoRange/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tcbrindle%2FNanoRange/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tcbrindle","download_url":"https://codeload.github.com/tcbrindle/NanoRange/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243719393,"owners_count":20336599,"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":["concepts","cplusplus","cplusplus-20","range","ranges-proposal"],"created_at":"2024-07-31T00:00:55.038Z","updated_at":"2025-03-15T18:35:09.262Z","avatar_url":"https://github.com/tcbrindle.png","language":"C++","readme":"\n[![Standard](https://img.shields.io/badge/c%2B%2B-17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)\n[![License](https://img.shields.io/badge/license-BSL-blue.svg)](http://www.boost.org/LICENSE_1_0.txt)\n[![Build Status](https://travis-ci.org/tcbrindle/NanoRange.svg?branch=master)](https://travis-ci.org/tcbrindle/NanoRange)\n[![Build status](https://ci.appveyor.com/api/projects/status/6vciaaskslg34pux/branch/master?svg=true)](https://ci.appveyor.com/project/tcbrindle/nanorange/branch/master) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://github.com/tcbrindle/NanoRange/raw/master/single_include/nanorange.hpp) \n[![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/g/Dbi77j) \n\n\n# NanoRange #\n\nNanoRange is a C++17 implementation of the C++20 Ranges proposals (formerly the\nRanges TS). It provides SFINAE-based implementations of all the proposed Concepts,\nand constrained and range-based versions the algorithms in the `\u003calgorithm\u003e`\nstandard library header.\n\nIt is intended for users who want range-based goodness in their C++, but don't\nwant to (or can't) use the full-blown\n [Range-V3][Range-V3]. It also aims to provide\n an easy upgrade path to standard ranges when they arrive.\n \nNanoRange is compatible with all three major C++ compilers, including the\nlatest version of Microsoft Visual C++.\n\n## Usage ##\n\nThe easiest way to use NanoRange is to simply download the [latest, automatically-generated \nsingle-header version](https://github.com/tcbrindle/NanoRange/raw/master/single_include/nanorange.hpp)\nand include it in your own sources like any other header. This is currently\nthe recommended way to use the library.\n\nAlternatively, you can clone this repository and use the individual headers in\nthe `include/nanorange` directory. This may give a slight boost to compile times,\nalthough there doesn't seem to be [too much difference](https://github.com/tcbrindle/NanoRange/wiki/Compile-times)\nat present. (In any case, the single-header version is similar to what you'll\nget when you `#include \u003calgorithm\u003e` in C++20).\n\nIf you use [Conan](https://conan.io) you can find the latest testing package at [bintray](https://bintray.com/dvirtz/conan/nanorange%3Atcbrindle) or just use the nanorange/20191001 package in conan-center.\n\nFinally, if you use [vcpkg], you can install the latest version of NanoRange from\nmaster using\n\n```\nvcpkg install nanorange --head\n```\n\n## Compatibility ##\n\nNanoRange requires a conforming C++17 compiler, and is\n[tested](https://travis-ci.org/tcbrindle/nanorange) with GCC 7 and Clang 4.0\nand newer. Older versions may work in some cases, but this is not guaranteed.\n\nIn addition, NanoRange works with MSVC 2017 version 15.9. Note that\nthe `/permissive-` switch is required for correct two-phase lookup.\n\n## Documentation ##\n\nThere is currently no reference documentation for NanoRange itself, but\nthe Ranges TS on which it is based is partially documented\n[on cppreference](http://en.cppreference.com/w/cpp/experimental/ranges).\n\n## What it provides ##\n\n### Concepts ###\n\nNanoRange provides all of the concepts from the ranges papers\nin the form of `constexpr bool` variable templates. You can use these to\nconstrain your own templates via `std::enable_if`, or in `if constexpr` \nstatements in C++17. For example\n\n```cpp\ntemplate \u003ctypename Rng\u003e\nvoid foo(Rng\u0026\u0026 rng) {\n    if constexpr (nano::RandomAccessRange\u003cRng\u003e) {\n         // do something\n    } else if constexpr (nano::BidirectionalRange\u003cRng\u003e\u003e) {\n        // do something else\n    } else if constexpr (nano::ForwardRange\u003cRng\u003e) {\n        // do a third thing\n    }\n}\n```\n\n### Iterator adaptors ###\n\nThe One Ranges proposal [P0896] adds two new iterator adaptors to the\nstandard library, namely `common_iterator` and `counted_iterator`,\nwhich are both implemented in NanoRange.\n\nAdditionally, [P0896] modifies the existing iterator adaptors for\ncompatibility with the new concepts. NanoRange therefore provides\ndrop-in replacements for these, specifically:\n\n * `reverse_iterator`\n * `front_insert_iterator`\n * `back_insert_iterator`\n * `insert_iterator`\n * `istream_iterator`\n * `ostream_iterator`\n * `istreambuf_iterator`\n * `ostreambuf_iterator`\n\nLastly, NanoRange provides an implementation of `subrange` from\n[P0896]. This can be used to turn an iterator/sentinel pair into in range,\nor as a `span`-like view of a subset of another range.\n\n### Algorithms ###\n\n#### Range-based overloads ####\n\nNanoRange provides range-based overloads of all the algorithms in `\u003calgorithm\u003e`.\nThis means that you can finally say\n\n```cpp\nstd::vector\u003cint\u003e vec{5, 4, 3, 2, 1};\nnano::sort(vec);\n```\n\nand it will Just Work.\n\n#### Constraint checking ####\n\nIn the existing STL, the algorithm calls are *unconstrained*. This means that\nif you pass an argument which doesn't meet the requirements of the function,\nthe compiler will go ahead and try to instantiate the template anyway,\nusually resulting in pages of error messages with template backtraces for\nwhich C++ is infamous.\n\nFor example, the following program has an error: a `std::list` iterator\nis not random-access, and so doesn't meet the requirements of `std::sort()`:\n\n```cpp\nint main()\n{\n    std::list\u003cint\u003e list{5, 4, 3, 2, 1};\n    std::sort(list.begin(), list.end());\n}\n```\n\nCompiling this two-line example with Clang 6.0 results in over [350 lines of error messages](https://gist.github.com/tcbrindle/13c23fc5c1a46db12665ee509bf8265f)!\n\nCalling `nano::sort()` instead of `std::sort()` on the other hand means that\nconstraints are checked before the template is instantated. This time, the\nentire error output is:\n\n```\nexample.cpp:9:5: error: no matching function for call to object of type 'const nano::ranges::detail::sort_fn'\n    nano::sort(list.begin(), list.end());\n    ^~~~~~~~~~\ninclude/nanorange/algorithm/stl/sort.hpp:26:5: note: candidate template ignored: requirement 'RandomAccessIterator\u003cstd::__1::__list_iterator\u003cint, void *\u003e \u003e' was not satisfied [with I = std::__1::__list_iterator\u003cint, void *\u003e, Comp = nano::ranges::less\u003cvoid\u003e]\n    operator()(I first, I last, Comp comp = Comp{}) const\n    ^\ninclude/nanorange/algorithm/stl/sort.hpp:37:5: note: candidate template ignored: substitution failure [with Rng = std::__1::__list_iterator\u003cint, void *\u003e, Comp = std::__1::__list_iterator\u003cint, void *\u003e]: no matching function for call to object of type 'const nano::ranges::detail::begin_::fn'\n    operator()(Rng\u0026\u0026 rng, Comp comp = Comp{}) const\n    ^\n1 error generated.\n```\n\nwhich makes it clear that the first overload was rejected because `list::iterator`\ndoesn't meet the requirements of `RandomAccessIterator`, and the second overload\nwas rejected because `list::iterator` is not a range (you can't call `nano::begin()`\non it). Much better.\n\n#### Function objects ####\n\nThe algorithms in NanoRange are implemented as non-template function objects with\ntemplated function call operators. This means that you can pass them around\nwithout needing to specify template arguments or wrap them in lambdas.\nFor example:\n\n```cpp\nstd::vector\u003cstd::vector\u003cint\u003e\u003e vec_of_vecs = ...\n\nnano::for_each(vec_of_vecs, nano::sort); // sorts each inner vector\n```\n\n#### Projections ####\n\nThe fully reimplemented algorithms (see below) offer support for *projections*.\nA projection is a unary callable which modifies (*\"projects\"*) the view of the data\nthat the algorithm sees. Because projections are routed through (an implementation\nof) `std::invoke()`, it's possible to use pointers to member functions and pointers\nto member data as projections. For example:\n\n```cpp\nstruct S {\n    int i;\n    float f;\n};\n\nstd::vector\u003cS\u003e vec = ...\n\nauto iter = nano::find(vec, 10, \u0026S::i);\n// iter points to the first member of vec for which i == 10\n```\n\n#### `constexpr` support ####\n\nIn [P0896], almost all the algorithms are marked  as `constexpr` (the exceptions\nbeing those which can potentially allocate temporary storage). NanoRange fully supports\nthis, meaning the vast majority of algorithms can be called at compile-time. For example\n\n```cpp\nauto sort_copy = [](auto rng) {\n    nano::sort(rng);\n    return rng;\n};\n\nint main()\n{\n    constexpr std::array a{5, 4, 3, 2, 1};\n    constexpr auto b = sort_copy(a);\n\n    static_assert(nano::is_sorted(b));\n}\n```\n\n## Ranges papers ##\n\nThe Ranges proposals have been consolidated into two main papers:\n\n * [P0898R3][P0898] *Standard library concepts*\n * [P0896R2][P0896] *The One Ranges Proposal*\n \n NanoRange fully implements the first, and implements most of the second (except\n for Views).\n\n## Stability ##\n\nNanoRange aims to track the various C++20 ranges proposals, and will be updated\nas new papers are published. As such, there are no API stability guarantees\nat this time.\n\n## Licence ##\n\nNanoRange is provided under the Boost licence. See LICENSE_1_0.txt for details.\n\n## Acknowledgements ##\n\nMany thanks to the following:\n\n * Eric Niebler and Casey Carter for the Ranges TS, Range-V3\n   and CMCSTL2. You guys are awesome.\n   \n * Orson Peters for [pdqsort]\n\n * Phil Nash for the fantastic Catch testing framework\n\n * The editors of [cppreference.com](https://cppreference.com) for painstakingly\n   detailing the existing requirements of standard library algorithms, and\n   more generally for maintaining the C++ programmer's bible.\n\n\u003c!-- References --\u003e\n\n[Range-V3]: https://github.com/ericniebler/range-v3/\n[P0898]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0898r3.pdf\n[P0896]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0896r2.pdf\n[pdqsort]: https://github.com/orlp/pdqsort\n[vcpkg]: https://github.com/Microsoft/vcpkg\n","funding_links":[],"categories":["Standard/Support Libraries","Containers and Algorithms"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftcbrindle%2FNanoRange","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftcbrindle%2FNanoRange","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftcbrindle%2FNanoRange/lists"}