C++ Logo

std-proposals

Advanced search

[std-proposals] consteval hashing of compile-time constant compound literals

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 14 May 2024 23:52:52 +0100
I'm experimenting with a consteval implementation of the MD5 hash
algorithm. I can write a switch statement with compile-time hashes as
follows:

    switch ( md5(some_runtime_value) )
    {
    case md5("dog"): return 1;
    case md5("cat"): return 2;
    case md5("cow"): return 3;
    }

The consteval implementation of 'md5' deals with a consteval array of
char's -- which is fine when you're hashing strings. It's a little
more complicated if you want to hash one of the following:

    int[3]
    tuple<int,char,bool>
    struct Monkey { int a, b; };

It gets complicated when you want to use std::bit_cast to convert one
of these three types to an std::array<char,N>, because std::bit_cast
doesn't yield a compile-time constant if the source type isn't
trivially copiable. (Most implementations of std::tuple are not
trivially copiable -- not even when all of the internal types are).

__builtin_bit_cast isn't much better. Nor is __builtin_memcpy.

If I want to hash an array of integers, I can use the following
consteval function to turn it into a char array:

        template<typename T, std::size_t N> requires std::is_integral_v<T>
        constexpr auto FromIntegralArray( T const (&arg)[N] )
        {
            using std::size_t;
            std::array<char, sizeof(arg)> retval{};
            for ( size_t i = 0u; i < sizeof(arg); ++i )
            {
                size_t const a = i / sizeof(T),
                            b = i % sizeof(T);

                retval[i] = arg[a] >> (CHAR_BIT * b);
            }
            return retval;
        }

But then I would need to (try to) write a function that would work
with floating points, tuples, and so on.

So is anyone talking about making bit_cast more versatile? Or even
allowing a consteval memcpy, so we can do this:

        template<typename T>
        constexpr auto FromIntegralArray( T const &arg )
        {
            using std::size_t;
            std::array<char, sizeof(arg)> retval{};
            std::memcpy( &retval.front(), &arg, sizeof retval );
            return retval;
        }

Received on 2024-05-14 22:53:04