The problem I am trying to solve is that, for readability of my code, I would like to use string literals instead of numerals. These should be converted to numerals at compile time (without additional preprocessing of the code).
In principle this should not be a problem nowadays, and actually the following seems to work:
constexpr unsigned long bogus_hash(char const *input) {
return input[0]+input[89];
}
constexpr unsigned long compute_hash(const char* a) {
return bogus_hash(a);
}
class HashedString {
public:
constexpr HashedString(const char* a): my_hash(compute_hash(a)) {};
constexpr HashedString(unsigned long a): my_hash(a) {};
constexpr unsigned long const& get() const {return my_hash;}
constexpr bool operator ==(const char* b) {
return my_hash == compute_hash(b);
};
protected:
unsigned long my_hash;
};
Almost: Of course, the hash function is use is not a good hash function. (The 89
in there is due to my test code:
int fun_new(HashedString a) {
return (a == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab");
}
int fun_old(std::string a) {
return (a == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab");
}
//#define CHOOSE fun_old
#define CHOOSE fun_new
int main() {
long res = 0;
for (long i = 0; i < 1000*1000*100; ++i) {
res += CHOOSE("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"); // will add 1
res += CHOOSE("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"); // will add 0
}
std::cout << "res = " << res << std::endl; // should return number of iterations in loop
return 0;
}
(Note that the internal use of hashes instead of the string literal is transparent to the caller of the function.)
My questions are:
Does the code actually do what I want it to? Timing the code shows that it does run much faster when using
HashedString
(fun_new
) instead ofstd::string
(fun_old
). (I am usingg++ 4.8.2
, with options-std=c++0x -O0
. Using-O1
seems to get rid of the loop completely?)Is there a compile-time hash function I can use for this purpose? All other (constexpr) hash functions I tried made the code run slower than before (likely because the constexpr is not evaluated at compile but at run-time.) I tried to use these: 1, 2, 3