user2576606
user2576606

Reputation: 35

How to make msvc 14 evaluate my constexpr at compile time

I am experimenting with c++ constexpr. I am implementing a HashedString class using FNV-1a hash.

Everything seems fine except that visual studio 2015 update 3 doesn't seem to evaluate the constexpr at compile time.

I added a static_assert and it shows no error, but in my test's disassembly it is clear that there is an explicit call to the constexpr function instead of the precomputed value.

I also tried with g++ and clang and they both are able to evaluate the constexpr at compile time.

Here is my test code:

#include <cstdint>
#include <cstddef>
#include <string>

class HashedString {
public:

//value working only for a 32bit hash
constexpr static size_t defaultOffset = 2166136261u;
constexpr static size_t prime = 16777619u;

/**
* Compute the hash of a string at compile time using FNV-1a hash
* https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80   %93Vo_hash_function
*/
template<std::size_t N>
constexpr HashedString(const char(&a)[N]) noexcept
    : mHash(hash(a))
#if defined(_DEBUG)
    , mString(a)
#endif
{
}
explicit constexpr HashedString(size_t h) noexcept : mHash(h) {}

constexpr static size_t hash(const char *const aString, const uint32_t val = defaultOffset) noexcept
{
    return (aString[0] == '\0') ? val : hash(&aString[1], (val ^ uint32_t(aString[0])) * prime);
}

constexpr bool operator==(const HashedString & hs) const { return mHash == hs.mHash; }
constexpr bool operator==(const size_t & h) const { return mHash == h; }
constexpr bool operator!=(const HashedString & hs) const { return mHash != hs.mHash; }
constexpr bool operator!=(const size_t & h) const { return mHash != h; }
constexpr bool operator<(const HashedString & hs) const { return mHash < hs.mHash; }

private:
    const size_t mHash = 0;
#if defined(_DEBUG)
    const char* mString = nullptr;
#endif
};

static_assert(HashedString("FNV Hash Test") == 0xF38B3DB9, "HashedString of 'FNV Hash Test' shoulb be equal to 0xF38B3DB9");

int main(int , char**) {
    constexpr HashedString hs("FNV Hash Test");
    return hs == 0xF38B3DB9;
}

So my question is: Is there a way to make visual studio compute my constexpr at compile time?

Upvotes: 1

Views: 711

Answers (1)

David Thomas
David Thomas

Reputation: 798

Changing main to:

constexpr auto hash = HashedString::hash("FNV Hash Test");
return hash == 0xF38B3DB9;

or

constexpr HashedString hs("FNV Hash Test");
constexpr auto answer = hs == 0xF38B3DB9;
return answer;

will cause the hash to be computed at compile time. The way your code was there was no demand on the compiler to compute the hash at compile-time. By requiring the compiler to initialize a constexpr variable, it is forced to compute the value at compile-time. Which reduced main's code to:

mov eax,1
ret

Booyah! for VS2015's SSA optimizations.

Upvotes: 1

Related Questions