Date: Fri, 24 Apr 2026 10:10:40 +0200
Just checking in to see if there's any interest in pursuing this further
On Apr 17, 2026, at 18:22, Robert Baumgartner <baumgar.robert_at_[hidden]> wrote:
Resending, as the previous mail did not include the mailing list.All questions and suggestions are addressed below.> Not really. If you have a fixed non-cryptographic hash function,
> I think it's practical to construct a set of keys that will cause
> so many collisions that nobody would call that O(1). A decade ago
> or so, people noticed that hashes are vulnerable to such targeted
> attacks, causing a denial-of-service vector for Internet-facing
> services that put user-supplied data into hash tables.You are referring to pathological datasets. They do exist indeed, and they should be strongly consideredin the design of unordered associative containers. For the intended use case this remains a run-timeconcern. Since the keys are compile time constants, an adversary cannot craft an attack vector atrun-time.Run-time of the containers can be probed during compilation, but can also be part of the interface, seemy following answers.> So, why don't we just standardize "frozen" or something similar?Indeed frozen provides a great interface, very in line with the stdlib.What frozen does not provide yet is a guaranteed interface and portability without a external libraries.It can however serve as a good guideline.> Having a "constexpr" replacement for GNU gperf (perfect hash
> function calculation) seems to be exactly what constant evaluation
> was made for.Indeed this could be one direction. A compile time hashing facility provides the lowest level of abstractionfor the problem I am trying to solve. We can look at the problem space roughly at 3 three layers:1. Hash construction2. Storage and solution layout (data structure, linear probing, ...)3. User facing containerA compile time hashing facility removes all abstraction and gives maximum control for the user at layer 1.The proposed std::static_unordered_set sits at layer 3., the highest level of abstraction. The question iswhich interface is the more suitable.What speaks for the compile time facility are clearly the degree of control it gives the user.The container on the other hand would be the more ergonomic solution for most users. It would providea familiar interface through the stdlib and abstract away the complexity of hash-functions, similar towhat the containers std::set and std::unordered_set do to the complexity they have under the hood.However, the two solutions can also integrate. The container should not depend on the compiletime facility below. The hash is a template parameter, hence the user can use a customized compiletime hash facility if wanted. But the solution can still draw from the strengths of a provided compile timehash solution by providing a default implementation.The point of such a solution has been raised in P3372R2 already, I cite in the following:Unordered containers needs a hashing facility. But default provided std::hash can’t be made constexpr
friendly as Cpp17Hash requirements states its result is guaranteed to be consistent only within duration
of the program. Intention is to allow salting the hash to avoid cache poisoning attacks. The requirement
is in a direct conflict with calculating the hash within constant evaluation. One possible solution would be
creating a std::stable_hash facility without such requirement. But this is a can of worms outside of
scope of this paper and I’m not brave enough to open it.
Using the container would provide the ergonomics for the typical use case of most users, who want a fast
lookup, without directly exposing the complexity underneath. A design like std::static_unordered_set<Key, N, Hash>
allows to choose strategies between compile time efficiency, size of underlying container, and run-time cost, without
directly exposing the implementation choices directly. The compile time hashing facility (something like gperf) provides
the user the tools for a more custom strategy if desired.Am Di., 14. Apr. 2026 um 21:35 Uhr schrieb Jens Maurer <jens.maurer_at_[hidden]>:
On 4/14/26 18:53, Robert Baumgartner wrote:
>> What doesn't work, for your use-case, using each of these approaches?
>
> frozen -> no guaranteed interface, no standard availability, adds an external dependency. The standard library should
> provide guaranteed portable solutions without external dependencies.
So, why don't we just standardize "frozen" or something similar?
Having a "constexpr" replacement for GNU gperf (perfect hash
function calculation) seems to be exactly what constant evaluation
was made for.
> The primary design
> would use open addressing with collision handling, just like a runtime std::unordered_set.
> O(1) at runtime is guaranteed through immutability of the array, hence fixed load factor.
Not really. If you have a fixed non-cryptographic hash function,
I think it's practical to construct a set of keys that will cause
so many collisions that nobody would call that O(1). A decade ago
or so, people noticed that hashes are vulnerable to such targeted
attacks, causing a denial-of-service vector for Internet-facing
services that put user-supplied data into hash tables.
Jens
Received on 2026-04-24 08:10:53
