1

I have implemented a constexpr compile-time hash-function, which works fine (i.e. is evaluated at compile-time) if called as

constexpr auto hash = CompileTimeHash( "aha" );

but I need to use it in actual code as an argument to a function as in

foo( CompileTimeHash( "aha" ) ); // foo is NOT constexpr

For a specific reason, I cannot use the long version

constexpr auto hash = CompileTimeHash( "aha" );
foo( hash );

The compiler (VC++) will not compile-time hash in the short (first) case. Is there any way to achieve this?

EDIT: An example covering the 3 cases is now found here: https://godbolt.org/z/JGAyuE Only gcc gets it done in all 3 cases

old123987
  • 121
  • 6

2 Answers2

9

Well, the as-if-rule always allows evaluation at runtime. However insane (and insanely complex) doing so might be.

Best shot to force your compiler to do it at compile-time, pass it through a template-argument:

A bit of setup:

template <auto x>
using make_integral_constant = std::integral_constant<decltype(x), x>;

template <auto x>
inline constexpr auto want_static = make_integral_constant<x>::value;

And use it like:

foo( want_static<CompileTimeHash( "aha" )> );

It works even without optimization, because unless you use an interpreter, doing it at runtime instead is too complex to do for no good reason.


Assigning to a constexpr-variable should also work. But it is actually easier to not evaluate at compile-time, so without optimization that happens anyway.

foo( []{ constexpr auto r = CompileTimeHash( "aha" ); return r; }() );

Update: In C++ 20 a new keyword consteval can be used to define an immediate function, which will always be evaluated at compile-time. constinit can be used to force initialization with constexpr rules without making it constexpr.

consteval auto immediate(auto x) { return x; }
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
-1

If I understand correctly, your CompileTimeHash() return a int.

So what about

foo( sizeof(char[CompileTimeHash( "aha" )]) );

?

If CompileTimeHash() return only positive numbers, obviously.

If CompileTimeHash() return non negative numbers (positive numbers or zero), you can solve the zero problem (not acceptable as size for a C-style array) adding (inside) and subtracting (outside) 1

I mean

foo( sizeof(char[CompileTimeHash( "aha" )+1])-1u );
max66
  • 65,235
  • 10
  • 71
  • 111
  • @old123987 - ehmm... no; if `CompileTimeHash()` return negative numbers or zero this can't work; but with positive numbers... – max66 Aug 24 '18 at 13:38
  • 1
    Even if it were an unsigned int rather than an int - this is a convoluted solution. Baroque, confusing, likely to be undone or otherwise abused by future maintainers. -1. – einpoklum Aug 24 '18 at 15:38
  • Even if it were an unsigned int, my solution is problematic for the zero case; I disagree with you for the following (convoluted, baroque, confusing...) but thanks for the explanation of your down-vote. – max66 Aug 24 '18 at 16:43