{"id":13677717,"url":"https://github.com/serge-sans-paille/frozen","last_synced_at":"2025-05-14T05:11:26.575Z","repository":{"id":21266558,"uuid":"92028303","full_name":"serge-sans-paille/frozen","owner":"serge-sans-paille","description":"a header-only, constexpr alternative to gperf for C++14 users","archived":false,"fork":false,"pushed_at":"2025-03-16T22:13:40.000Z","size":631,"stargazers_count":1408,"open_issues_count":37,"forks_count":108,"subscribers_count":39,"default_branch":"master","last_synced_at":"2025-05-12T13:08:55.671Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/serge-sans-paille.png","metadata":{"files":{"readme":"README.rst","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":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-22T08:09:44.000Z","updated_at":"2025-05-11T00:51:53.000Z","dependencies_parsed_at":"2023-01-13T21:22:24.572Z","dependency_job_id":"d7d98621-a2a6-445f-bb0c-3c6f2e6ff34f","html_url":"https://github.com/serge-sans-paille/frozen","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serge-sans-paille%2Ffrozen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serge-sans-paille%2Ffrozen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serge-sans-paille%2Ffrozen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/serge-sans-paille%2Ffrozen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/serge-sans-paille","download_url":"https://codeload.github.com/serge-sans-paille/frozen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253747233,"owners_count":21957720,"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":[],"created_at":"2024-08-02T13:00:46.155Z","updated_at":"2025-05-14T05:11:21.564Z","avatar_url":"https://github.com/serge-sans-paille.png","language":"C++","funding_links":[],"categories":["Containers","C++","Data Structures and Algorithms"],"sub_categories":[],"readme":"Frozen\n######\n\n.. image:: https://travis-ci.org/serge-sans-paille/frozen.svg?branch=master\n   :target: https://travis-ci.org/serge-sans-paille/frozen\n\nHeader-only library that provides 0 cost initialization for immutable containers, fixed-size containers, and various algorithms.\n\nFrozen provides:\n\n- immutable (a.k.a. frozen), ``constexpr``-compatible versions of ``std::set``,\n  ``std::unordered_set``, ``std::map`` and ``std::unordered_map``.\n  \n- fixed-capacity, ``constinit``-compatible versions of ``std::map`` and \n  ``std::unordered_map`` with immutable, compile-time selected keys mapped\n  to mutable values.\n\n- 0-cost initialization version of ``std::search`` for frozen needles using\n  Boyer-Moore or Knuth-Morris-Pratt algorithms.\n\n\nThe ``unordered_*`` containers are guaranteed *perfect* (a.k.a. no hash\ncollision) and the extra storage is linear with respect to the number of keys.\n\nOnce initialized, the container keys cannot be updated, and in exchange, lookups\nare faster. And initialization is free when ``constexpr`` or ``constinit`` is \nused :-).\n\nStable Version\n--------------\n\nThe Frozen library is pretty stable now, have been so for years, so:\n\n1. The ``master`` version can be used as the default **stable** version.\n2. It is in maintenance mode. I still accept commits that make the code cleaner\n   ``|`` faster ``|`` more modern, but expect some latency in the review process.\n\n\nInstallation\n------------\n\nJust copy the ``include/frozen`` directory somewhere and points to it using the ``-I`` flag. Alternatively, using CMake:\n\n.. code:: sh\n\n    \u003e mkdir build\n    \u003e cd build\n    \u003e cmake -D CMAKE_BUILD_TYPE=Release ..\n    \u003e make install\n\n\nInstallation via CMake populates configuration files into the ``/usr/local/share``\ndirectory which can be consumed by CMake's ``find_package`` instrinsic function.\n\nRequirements\n------------\n\nA C++ compiler that supports C++14. Clang version 5 is a good pick, GCC version\n6 lags behind in terms of ``constexpr`` compilation time (At least on my\nsetup), but compiles correctly. Visual Studio 2017 also works correctly!\n\nNote that gcc 5 isn't supported. (Here's an `old compat branch`_ where a small amount of stuff was ported.)\n\n.. _old compat branch: https://github.com/cbeck88/frozen/tree/gcc5-support\n\nUsage\n-----\n\nCompiled with ``-std=c++14`` flag:\n\n.. code:: C++\n\n    #include \u003cfrozen/set.h\u003e\n\n    constexpr frozen::set\u003cint, 4\u003e some_ints = {1,2,3,5};\n\n    constexpr bool letitgo = some_ints.count(8);\n\n    extern int n;\n    bool letitgoooooo = some_ints.count(n);\n\n\nAs the constructor and some methods are ``constexpr``, it's also possible to write weird stuff like:\n\n.. code:: C++\n\n    #include \u003cfrozen/set.h\u003e\n\n    template\u003cstd::size_t N\u003e\n    std::enable_if_t\u003c frozen::set\u003cint, 3\u003e{{1,11,111}}.count(N), int\u003e foo();\n\nString support is built-in:\n\n.. code:: C++\n\n    #include \u003cfrozen/unordered_map.h\u003e\n    #include \u003cfrozen/string.h\u003e\n\n    constexpr frozen::unordered_map\u003cfrozen::string, int, 2\u003e olaf = {\n        {\"19\", 19},\n        {\"31\", 31},\n    };\n    constexpr auto val = olaf.at(\"19\");\n\nThe associative containers have different functionality with and without ``constexpr``. \nWith ``constexpr``, frozen maps have immutable keys and values. Without ``constexpr``, the \nvalues can be updated in runtime (the keys, however, remain immutable):\n\n.. code:: C++\n\n\n    #include \u003cfrozen/unordered_map.h\u003e\n    #include \u003cfrozen/string.h\u003e\n\n    static constinit frozen::unordered_map\u003cfrozen::string, frozen::string, 2\u003e voice = {\n        {\"Anna\", \"???\"},\n        {\"Elsa\", \"???\"}\n    };\n    \n    int main() {\n    \tvoice.at(\"Anna\") = \"Kristen\";\n\tvoice.at(\"Elsa\") = \"Idina\";\n    }\n\nYou may also prefer a slightly more DRY initialization syntax:\n\n.. code:: C++\n\n    #include \u003cfrozen/set.h\u003e\n\n    constexpr auto some_ints = frozen::make_set\u003cint\u003e({1,2,3,5});\n\nThere are similar ``make_X`` functions for all frozen containers.\n\nException Handling\n------------------\n\nFor compatibility with STL's API, Frozen may eventually throw exceptions, as in\n``frozen::map::at``. If you build your code without exception support, or\ndefine the ``FROZEN_NO_EXCEPTIONS`` macro variable, they will be turned into an\n``std::abort``.\n\nExtending\n---------\n\nJust like the regular C++14 container, you can specialize the hash function,\nthe key equality comparator for ``unordered_*`` containers, and the comparison\nfunctions for the ordered version.\n\nIt's also possible to specialize the ``frozen::elsa`` structure used for\nhashing. Note that unlike `std::hash`, the hasher also takes a seed in addition\nto the value being hashed.\n\n.. code:: C++\n\n    template \u003cclass T\u003e struct elsa {\n      // in case of collisions, different seeds are tried\n      constexpr std::size_t operator()(T const \u0026value, std::size_t seed) const;\n    };\n\nIdeally, the hash function should have nice statistical properties like *pairwise-independence*:\n\nIf ``x`` and ``y`` are different values, the chance that ``elsa\u003cT\u003e{}(x, seed) == elsa\u003cT\u003e{}(y, seed)``\nshould be very low for a random value of ``seed``.\n\nNote that frozen always ultimately produces a perfect hash function, and you will always have ``O(1)``\nlookup with frozen. It's just that if the input hasher performs poorly, the search will take longer and\nyour project will take longer to compile.\n\nTroubleshooting\n---------------\n\nIf you hit a message like this:\n\n.. code:: none\n\n    [...]\n    note: constexpr evaluation hit maximum step limit; possible infinite loop?\n\nThen either you've got a very big container and you should increase Clang's\nthresholds, using ``-fconstexpr-steps=1000000000`` for instance, or the hash\nfunctions used by frozen do not suit your data, and you should change them, as\nin the following:\n\n.. code:: c++\n\n    struct olaf {\n      constexpr std::size_t operator()(frozen::string const \u0026value, std::size_t seed) const { return seed ^ value[0];}\n    };\n\n    constexpr frozen::unordered_set\u003cfrozen::string, 2, olaf/*custom hash*/\u003e hans = { \"a\", \"b\" };\n\nTests and Benchmarks\n--------------------\n\nUsing hand-written Makefiles crafted with love and care:\n\n.. code:: sh\n\n    \u003e # running tests\n    \u003e make -C tests check\n    \u003e # running benchmarks\n    \u003e make -C benchmarks GOOGLE_BENCHMARK_PREFIX=\u003cGOOGLE-BENCHMARK_INSTALL_DIR\u003e\n\nUsing CMake to generate a static configuration build system:\n\n.. code:: sh\n\n    \u003e mkdir build\n    \u003e cd build\n    \u003e cmake -D CMAKE_BUILD_TYPE=Release \\\n            -D frozen.benchmark=ON \\\n\t    -G \u003c\"Unix Makefiles\" or \"Ninja\"\u003e ..\n    \u003e # building the tests and benchmarks...\n    \u003e make                               # ... with make\n    \u003e ninja                              # ... with ninja\n    \u003e cmake --build .                    # ... with cmake\n    \u003e # running the tests...\n    \u003e make test                          # ... with make\n    \u003e ninja test                         # ... with ninja\n    \u003e cmake --build . --target test      # ... with cmake\n    \u003e ctest                              # ... with ctest\n    \u003e # running the benchmarks...\n    \u003e make benchmark                     # ... with make\n    \u003e ninja benchmark                    # ... with ninja\n    \u003e cmake --build . --target benchmark # ... with cmake\n\nUsing CMake to generate an IDE build system with test and benchmark targets\n\n.. code:: sh\n\n    \u003e mkdir build\n    \u003e cd build\n    \u003e cmake -D frozen.benchmark=ON -G \u003c\"Xcode\" or \"Visual Studio 15 2017\"\u003e ..\n    \u003e # using cmake to drive the IDE build, test, and benchmark\n    \u003e cmake --build . --config Release\n    \u003e cmake --build . --target test\n    \u003e cmake --build . --target benchmark\n\n\nCredits\n-------\n\nThe perfect hashing is strongly inspired by the blog post `Throw away the keys:\nEasy, Minimal Perfect Hashing \u003chttp://stevehanov.ca/blog/index.php?id=119\u003e`_.\n\nThanks a lot to Jérôme Dumesnil for his high-quality reviews, and to Chris Beck\nfor his contributions on perfect hashing.\n\nContact\n-------\n\nSerge sans Paille ``\u003cserge.guelton@telecom-bretagne.eu\u003e``\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserge-sans-paille%2Ffrozen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fserge-sans-paille%2Ffrozen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fserge-sans-paille%2Ffrozen/lists"}