views:

424

answers:

4

Is there any way to create a hash of string at compile time using the C/C++ preprocessor (or even template-metaprogramming)?

e.g. UNIQUE_SALT("HelloWord", 3DES);

The idea is that HelloWorld will not be present in the compiled binary, just a hash.

Edit: There are many of these declarations spread over a large codebase.

+4  A: 

This can be done with Boost.MPL but it might not be the type of hash you are after.

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

Eddy Pronk
Thanks, that about as close as it gets however I guess as per Georg's answer current C++ simply isn't capable. I guess other similar questions here on SO should have alerted me to that. If I could accept two answers I'd accept yours too.
AshirusNW
+7  A: 

Why not make generating the hash part of your build process? You can write a simple batch file to generate the hash (assuming you have a program to do such a thing - if not, write one) and have it output a preprocessor directive something like:

#define MY_HASH 123456789 

to a .h file that then gets #included in your application.

anon
My problem isn't generating a hash, it's finding and replacing these strings with their hashes at compile-time. The only way I can think of doing this is using a pre-processor hack. There are many of these UNIQUE_SALT("Some string", xxx) declarations in the source control.
AshirusNW
@Ashirus Well, I still think the best way to deal with them is to centralise them, and then generate the required definitions somehow.
anon
A prebuild step is easy! After all, it's just some pattern matching / replace. Any scripting language will allow you do it, and it'll become as transparent as the use of the preprocessor.
Matthieu M.
@Neil. They can't be centralised. They are spread all over the source code (which is over 1M LOC and not under my control). Such is the problem space.
AshirusNW
@Matthieu: But then I would be require the codebase's 10,000 developers to run a specific extra tool before compilation - it's got to be part of the standard toolchain.
AshirusNW
@All I appreciate these alternative approaches but really, you're asking me to redefine the problem space and assuming I have a level of contorl over the codebase and toolchain that I simply do not have, but thanks anyway.
AshirusNW
+3  A: 

There is no compile time string processing in C++. With the preprocessor you can't seperate the string into tokens, with templates you can't access single characters. There was however a discussion on the speculated approach using C++0x.

What you can do now is to pass the string character-wise (possible using multi-character literals):

foo = hash<3DES, str<'a','b','c'> >::result;
// or:
foo = hash<3DES, str<'abc','def'> >::result;

... or simply do it as a pre-build step.

Georg Fritzsche
how does "hash<3DES, str<'abc','def'> >::result" work and why can't you do "hash<3DES, str<'verylong string','even longer string'> >::result"?
AshirusNW
@Ashirus: These are *multicharacter literals*, have type `int` and *"implementation defined value"*. Longer values simply wouldn't fit into an `int` and you still have to get the seperate character values out manually.
Georg Fritzsche
+1  A: 

Even if this can't be (reasonably) done with the preprocessor, if you used a string literal or declared it as static const and did not create any lasting references to it the compiler will likely go ahead and do all of the math to generate the result and omit the string in the object file if you compile with optimizations. The hardest part of this is that you can't make the code to initialize a global or static variable too complicated or the compiler will say "hey, you! Don't you know you can't use a for loop outside of a function?".

nategoose
That's a good point, however I need to be certain that there are no references as there are many declarations and binary size is very important.
AshirusNW
I really don't think your compiler is going to optimise a hash algorithm out of existence even if all the data is const - they are clever but not even nearly that clever.
Elemental