0

I would like to initialise a struct member with a hash of the struct name.

constexpr uint32_t myHash(const char* const data)
{ //Some code for hash
    return myHash;
}

struct My_Struct{
    constexpr Test() : ID(myHash("My_Struct"))
    {
    }
    const uint32_t ID; 
}

When I have:

constexpr My_Struct my_constexpr_struct;

Then the hash is computed at compile time successfully. However, when I have in my main function

My_Struct my_normal_struct;

then it will call the

constexpr uint32_t myHash(const char* const data)

function in the code instead of simply initialising the struct member with a compile time constant.

This would obviously incur a significant performance penalty that is avoidable.

Any thoughts or suggestions on how to have the compiler perform this at compile time? I don't really want to do:

constexpr uint32_t MY_STRUCT_ID = myHash("My_Struct");
struct My_Struct{
    constexpr Test() : ID(MY_STRUCT_ID)
    {
    }
    const uint32_t ID; 

Thanks.

Flip
  • 881
  • 7
  • 13

1 Answers1

5

constexpr is a request, not a requirement. As such, if you initialize an object outside of a constant expression context, even through a constexpr constructor, there is no guarantee that the initialization will be done at compile time.

If you want to guarantee compile-time evaluation, you have to call the constexpr function it in a constant expression context. If the explicit use of a variable offends you in some way, you could always force constexpr evaluation through the use of a template:

template<typename T, T t>
struct repeat
{
  using value_type = T;
  static constexpr T value = t;
  constexpr T operator()() const noexcept {return t;}
};

struct My_Struct{
    constexpr My_Struct() : ID(repeat<uint32_t, myHash("My_Struct")>::value)
    {
    }
    const uint32_t ID; 
};
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982