9

Basically I need a truly compile-time string hashing in C++. I don't care about technique specifics, can be templates, macros, anything. All other hashing techniques I've seen so far can only generate hashtable (like 256 CRC32 hashes) in compile time, not a real hash.

In other words, I need to have this

printf("%d", SOMEHASH("string"));

to be compiled as (in pseudo-assembler)

push HASHVALUE
push "%d"
call printf

even in Debug builds, with no runtime operations on string. I am using GCC 4.2 and Visual Studio 2008 and I need the solution to be OK for those compilers (so no C++0x).

John
  • 2,295
  • 1
  • 20
  • 25
  • Sounds like rentacoder. Since it's not possible without C++0x, I guess you will have to write compiler plugins for GCC and MSVC. – Johannes Schaub - litb Jun 23 '11 at 16:59
  • I don't think this is possible in plain C++. Is the overhead of runtime hashing the compiled strings really all that expensive? – Billy ONeal Jun 23 '11 at 17:00
  • @Johannes: It's possible in C++0x? – Billy ONeal Jun 23 '11 at 17:01
  • @Billy ONeal: I think it will be with user-defined literals, no? – jason Jun 23 '11 at 17:01
  • @Billy several people have demonstrated that operations on string literals can be done at compile time in C++0x. – Johannes Schaub - litb Jun 23 '11 at 17:02
  • @Jason: I thought user defined literals were just syntactic sugar for a function call. – Billy ONeal Jun 23 '11 at 17:03
  • 4
    @Billy: That call can be constexpr. – Puppy Jun 23 '11 at 17:09
  • @DeadMG: Oh! Awesome! (Can't wait until compilers finish implementing this thing...) – Billy ONeal Jun 23 '11 at 17:28
  • Since you're using gcc, this is actually not much trouble. It will evaluate a hash as plain normal inline function on a string literal up to 16 characters long (not counting the terminator) just fine with default settings (`for` loop over array with `strlen`). If you need to hash longer strings, you have to tweak the maximum inline recursion depth parameter. This is kind of stupid since it takes extra parameters on the commandline, but it works ok. – Damon Jun 23 '11 at 21:07

6 Answers6

7

The trouble is that in C++03 the result of subscripting a string literal (i.e. access a single character) is not a compile-time constant suitable for use as a template parameter.

It is therefore not possible to do this. I would recommend you to write a script to compute the hashes and insert them directly into the source code, i.e.

printf("%d", SOMEHASH("string"));

gets converted to

printf("%d", 257359823 /*SOMEHASH("string")*/ ));

Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
6

Write your own preprocessor that scans the source for SOMEHASH("") and replaces it with the computed hash. Then pass the output of that to the compiler.

(Similar techniques are used for I18N.)

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • 1
    Intrigued to get both an upvote and a downvote on this. Why? It's a hack, but one that is useful in some contexts, and it does seem to fit the specified requirements. – Alan Stokes Jun 23 '11 at 19:46
3

With templates only the following syntax will work: SOMEHASH<'s','t','r','i','n','g'>

see this eg: http://arcticinteractive.com/2009/04/18/compile-time-string-hashing-boost-mpl/ or compile-time string hashing

Community
  • 1
  • 1
1

You have to wait for user-defined literals in C++0x for this.

jason
  • 236,483
  • 35
  • 423
  • 525
0

If you don't mind using the new C++0x standard in your code (some answers also include links to stuff that works in the older C++03 standard), these questions have been asked before on StackOverflow:

Compile-time (preprocessor) hashing of string
Compile time string hashing

Both of those contain answers that will help you figure out how to possibly implement this.

Here is a blog post that shows how to use Boost.MPL Compile Time String Hashing

Community
  • 1
  • 1
X-Istence
  • 16,324
  • 6
  • 57
  • 74
  • If you had taken the time to read any of the questions you would also see answers that are not specific to C++0x. Including Boost.MPL for example. – X-Istence Jun 23 '11 at 18:55
-2

That's not possible, it might be in C++0x but definitely not in C++03.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    This provides no insight. You might be right, or you might be wrong. From reading your answer, who knows? – quant Sep 10 '14 at 23:00