Is there any substitution for compile time hash as template arguments

117 Views Asked by At

I am making a string class whose construction relies on its hash value:

template <size_t N>
static inline constexpr uint64_t hash(const char(&str)[N])
{
    //...
}

class String()
{
    // Wrong
    template <size_t N>
    String(const char(&str)[N]) { hash(str)... }

    // Right
    template <uint64_t hash, size_t N>
    String(const char(&str)[N]) { hash...}
}

In the wrong version, if I use "hash" as constexpr, the "str" is out of its life period. But if not, the constexpr function is meaningless. Maybe I have to treat hash value as template arguments(?)

In that case, I have to use it like:

    // Simple but wrong
    String str("Hello World");

    // Right but complex
    String<hash("Hello World")> str("Hello World");
    
    // The worst
    class Test
    {
    public:
        Test()
        : name("Hello World") // ???
        {}
    private:
        String name;
    }

Macros work, but it is also hard to use String as member variables. Is there any better design?

1

There are 1 best solutions below

0
Artyer On BEST ANSWER

You can pass the string literal as a template parameter once using a helper class:

template<size_t N>
struct literal_string {
    constexpr literal_string(const char(& arr)[N]) {
        std::ranges::copy(arr, data);
    }

    constexpr operator std::string_view() const noexcept { return { data, N }; };

    char data[N];
};

template<literal_string S>
struct String {
    static constexpr uint64_t hash_value = hash(S.data);

    constexpr String() {
        // You have access to both S.data and hash_value here
    }
};

String<"Hello World"> str;