frozen/1.0.1

[brief]

a header-only, constexpr alternative to gperf for C++14 users

Frozen
######

.. image:: https://travis-ci.org/serge-sans-paille/frozen.svg?branch=master
   :target: https://travis-ci.org/serge-sans-paille/frozen

Header-only library that provides 0 cost initialization for immutable containers, fixed-size containers, and various algorithms.

Frozen provides:

- immutable (a.k.a. frozen), ``constexpr``-compatible versions of ``std::set``,
  ``std::unordered_set``, ``std::map`` and ``std::unordered_map``.
  
- fixed-capacity, ``constinit``-compatible versions of ``std::map`` and 
  ``std::unordered_map`` with immutable, compile-time selected keys mapped
  to mutable values.

- 0-cost initialization version of ``std::search`` for frozen needles using
  Boyer-Moore or Knuth-Morris-Pratt algorithms.


The ``unordered_*`` containers are guaranteed *perfect* (a.k.a. no hash
collision) and the extra storage is linear with respect to the number of keys.

Once initialized, the container keys cannot be updated, and in exchange, lookups
are faster. And initialization is free when ``constexpr`` or ``constinit`` is 
used :-).


Installation
------------

Just copy the ``include/frozen`` directory somewhere and points to it using the ``-I`` flag. Alternatively, using CMake:

.. code:: sh

    > mkdir build
    > cd build
    > cmake -D CMAKE_BUILD_TYPE=Release ..
    > make install


Installation via CMake populates configuration files into the ``/usr/local/share``
directory which can be consumed by CMake's ``find_package`` instrinsic function.

Requirements
------------

A C++ compiler that supports C++14. Clang version 5 is a good pick, GCC version
6 lags behind in terms of ``constexpr`` compilation time (At least on my
setup), but compiles correctly. Visual Studio 2017 also works correctly!

Note that gcc 5 isn't supported. (Here's an `old compat branch`_ where a small amount of stuff was ported.)

.. _old compat branch: https://github.com/cbeck88/frozen/tree/gcc5-support

Usage
-----

Compiled with ``-std=c++14`` flag:

.. code:: C++

    #include <frozen/set.h>

    constexpr frozen::set<int, 4> some_ints = {1,2,3,5};

    constexpr bool letitgo = some_ints.count(8);

    extern int n;
    bool letitgoooooo = some_ints.count(n);


As the constructor and some methods are ``constexpr``, it's also possible to write weird stuff like:

.. code:: C++

    #include <frozen/set.h>

    template<std::size_t N>
    std::enable_if_t< frozen::set<int, 3>{{1,11,111}}.count(N), int> foo();

String support is built-in:

.. code:: C++

    #include <frozen/unordered_map.h>
    #include <frozen/string.h>

    constexpr frozen::unordered_map<frozen::string, int, 2> olaf = {
        {"19", 19},
        {"31", 31},
    };
    constexpr auto val = olaf.at("19");

The associative containers have different functionality with and without ``constexpr``. 
With ``constexpr``, frozen maps have immutable keys and values. Without ``constexpr``, the 
values can be updated in runtime (the keys, however, remain immutable):

.. code:: C++


    #include <frozen/unordered_map.h>
    #include <frozen/string.h>

    static constinit frozen::unordered_map<frozen::string, frozen::string, 2> voice = {
        {"Anna", "???"},
        {"Elsa", "???"}
    };
    
    int main() {
    	voice.at("Anna") = "Kristen";
	voice.at("Elsa") = "Idina";
    }

You may also prefer a slightly more DRY initialization syntax:

.. code:: C++

    #include <frozen/set.h>

    constexpr auto some_ints = frozen::make_set<int>({1,2,3,5});

There are similar ``make_X`` functions for all frozen containers.

Exception Handling
------------------

For compatibility with STL's API, Frozen may eventually throw exceptions, as in
``frozen::map::at``. If you build your code without exception support, or
define the ``FROZEN_NO_EXCEPTIONS`` macro variable, they will be turned into an
``std::abort``.

Extending
---------

Just like the regular C++14 container, you can specialize the hash function,
the key equality comparator for ``unordered_*`` containers, and the comparison
functions for the ordered version.

It's also possible to specialize the ``frozen::elsa`` structure used for
hashing. Note that unlike `std::hash`, the hasher also takes a seed in addition
to the value being hashed.

.. code:: C++

    template <class T> struct elsa {
      // in case of collisions, different seeds are tried
      constexpr std::size_t operator()(T const &value, std::size_t seed) const;
    };

Ideally, the hash function should have nice statistical properties like *pairwise-independence*:

If ``x`` and ``y`` are different values, the chance that ``elsa<T>{}(x, seed) == elsa<T>{}(y, seed)``
should be very low for a random value of ``seed``.

Note that frozen always ultimately produces a perfect hash function, and you will always have ``O(1)``
lookup with frozen. It's just that if the input hasher performs poorly, the search will take longer and
your project will take longer to compile.

Troubleshooting
---------------

If you hit a message like this:

.. code:: none

    [...]
    note: constexpr evaluation hit maximum step limit; possible infinite loop?

Then either you've got a very big container and you should increase Clang's
thresholds, using ``-fconstexpr-steps=1000000000`` for instance, or the hash
functions used by frozen do not suit your data, and you should change them, as
in the following:

.. code:: c++

    struct olaf {
      constexpr std::size_t operator()(frozen::string const &value, std::size_t seed) const { return seed ^ value[0];}
    };

    constexpr frozen::unordered_set<frozen::string, 2, olaf/*custom hash*/> hans = { "a", "b" };

Tests and Benchmarks
--------------------

Using hand-written Makefiles crafted with love and care:

.. code:: sh

    > # running tests
    > make -C tests check
    > # running benchmarks
    > make -C benchmarks GOOGLE_BENCHMARK_PREFIX=<GOOGLE-BENCHMARK_INSTALL_DIR>

Using CMake to generate a static configuration build system:

.. code:: sh

    > mkdir build
    > cd build
    > cmake -D CMAKE_BUILD_TYPE=Release \
            -D frozen.benchmark=ON \
	    -G <"Unix Makefiles" or "Ninja"> ..
    > # building the tests and benchmarks...
    > make                               # ... with make
    > ninja                              # ... with ninja
    > cmake --build .                    # ... with cmake
    > # running the tests...
    > make test                          # ... with make
    > ninja test                         # ... with ninja
    > cmake --build . --target test      # ... with cmake
    > ctest                              # ... with ctest
    > # running the benchmarks...
    > make benchmark                     # ... with make
    > ninja benchmark                    # ... with ninja
    > cmake --build . --target benchmark # ... with cmake

Using CMake to generate an IDE build system with test and benchmark targets

.. code:: sh

    > mkdir build
    > cd build
    > cmake -D frozen.benchmark=ON -G <"Xcode" or "Visual Studio 15 2017"> ..
    > # using cmake to drive the IDE build, test, and benchmark
    > cmake --build . --config Release
    > cmake --build . --target test
    > cmake --build . --target benchmark


Credits
-------

The perfect hashing is strongly inspired by the blog post `Throw away the keys:
Easy, Minimal Perfect Hashing <http://stevehanov.ca/blog/index.php?id=119>`_.

Thanks a lot to Jérôme Dumesnil for his high-quality reviews, and to Chris Beck
for his contributions on perfect hashing.

Contact
-------

Serge sans Paille ``<serge.guelton@telecom-bretagne.eu>``

version 1.0.1
license Apache-2.0
repository https://pkg.cppget.org/1/stable
download frozen-1.0.1.tar.gz
sha256 dceb7abe2f660d98fb6e00396a7d26b47c8fe5d1f25e72649b83b90482bdbb92
project frozen
url github.com/serge-sans-paille/frozen

Reviews

fail 0
pass 1

Builds

toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.10-O2
timestamp 2025-08-24 04:42:12 UTC (10:49 minutes ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.10-static_O2
timestamp 2025-08-24 04:41:14 UTC (11:47 minutes ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.10
timestamp 2025-08-24 04:39:46 UTC (13:15 minutes ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-clang_18_llvm_msvc_17.10-static_O2
timestamp 2025-08-24 02:16:19 UTC (02:36:43 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.8-static_O2
timestamp 2025-08-24 02:15:42 UTC (02:37:19 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.8-O2
timestamp 2025-08-24 02:14:49 UTC (02:38:13 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-clang_18_llvm_msvc_17.10-O2
timestamp 2025-08-24 02:14:35 UTC (02:38:26 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-msvc_17.8
timestamp 2025-08-24 02:13:00 UTC (02:40:01 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-clang_18_llvm_msvc_17.10
timestamp 2025-08-24 02:12:56 UTC (02:40:05 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-microsoft-win32-msvc14.3
tgt config windows_10-clang_17_msvc_msvc_17.10
timestamp 2025-08-24 02:03:00 UTC (02:50:01 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-freebsd13.3
tgt config freebsd_13-clang_17
timestamp 2025-08-24 01:46:48 UTC (03:06:13 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-freebsd14.1
tgt config freebsd_14-clang_18-static_O3
timestamp 2025-08-24 01:43:17 UTC (03:09:45 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-freebsd14.1
tgt config freebsd_14-clang_18-O3
timestamp 2025-08-24 01:41:28 UTC (03:11:33 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-freebsd14.1
tgt config freebsd_14-clang_18
timestamp 2025-08-24 01:39:55 UTC (03:13:06 hours ago)
result success | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_fedora_40-gcc_14-bindist
timestamp 2025-08-23 11:03:21 UTC (17:49:40 hours ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-gcc_14-O3
timestamp 2025-08-21 12:50:58 UTC (02 16:02:04 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-gcc_14
timestamp 2025-08-21 11:49:52 UTC (02 17:03:10 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-gcc_14-ndebug_O3
timestamp 2025-08-21 11:48:44 UTC (02 17:04:17 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-gcc_14-static_O3
timestamp 2025-08-21 11:46:39 UTC (02 17:06:22 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_ubuntu_24.04-gcc_13-bindist
timestamp 2025-08-21 11:25:59 UTC (02 17:27:02 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-w64-mingw32
tgt config windows_10-gcc_13.2_mingw_w64-O2
timestamp 2025-08-21 11:16:37 UTC (02 17:36:25 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-w64-mingw32
tgt config windows_10-gcc_13.2_mingw_w64-static_O2
timestamp 2025-08-21 11:16:17 UTC (02 17:36:44 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-w64-mingw32
tgt config windows_10-gcc_13.2_mingw_w64
timestamp 2025-08-21 11:15:51 UTC (02 17:37:10 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_12-bindist
timestamp 2025-08-21 11:09:19 UTC (02 17:43:43 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_14-static_O3
timestamp 2025-08-21 11:06:31 UTC (02 17:46:31 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18_libc++
timestamp 2025-08-21 11:06:13 UTC (02 17:46:48 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18_libc++-O3
timestamp 2025-08-21 11:05:19 UTC (02 17:47:42 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18_libc++-static_O3
timestamp 2025-08-21 11:05:08 UTC (02 17:47:54 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18-O3
timestamp 2025-08-21 11:04:47 UTC (02 17:48:14 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18-static_O3
timestamp 2025-08-21 11:04:14 UTC (02 17:48:47 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_14
timestamp 2025-08-21 11:03:33 UTC (02 17:49:29 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_14-O3
timestamp 2025-08-21 11:03:10 UTC (02 17:49:52 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_18
timestamp 2025-08-21 11:02:50 UTC (02 17:50:11 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_14-ndebug_O3
timestamp 2025-08-21 11:02:38 UTC (02 17:50:24 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_17_libc++
timestamp 2025-08-21 10:54:05 UTC (02 17:58:56 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_17
timestamp 2025-08-21 10:53:07 UTC (02 17:59:54 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-gcc_13.1
timestamp 2025-08-21 10:51:31 UTC (02 18:01:31 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_17
timestamp 2025-08-21 10:36:01 UTC (02 18:17:00 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-clang_17_libc++
timestamp 2025-08-21 10:35:18 UTC (02 18:17:43 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target aarch64-linux-gnu
tgt config linux_debian_12-gcc_13
timestamp 2025-08-21 10:29:29 UTC (02 18:23:32 days ago)
result error (update) | log | rebuild
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18-O3
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18-static_O3
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18_libc++
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18_libc++-O3
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_debian_12-clang_18_libc++-static_O3
result unbuilt
toolchain public-0.17.0
target x86_64-linux-gnu
tgt config linux_fedora_39-gcc_13-bindist
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin22.5.0
tgt config macos_13-clang_15.0
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-clang_15.0
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-clang_15.0-O3
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-clang_15.0-static_O3
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-gcc_14_homebrew
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-gcc_14_homebrew-O3
result unbuilt
toolchain public-0.17.0
target x86_64-apple-darwin23.5.0
tgt config macos_14-gcc_14_homebrew-static_O3
result unbuilt