用于长字符串(文字)的编译时哈希函数

时间:2015-01-31 11:25:33

标签: c++ hash constexpr compile-time string-literals

我想解决的问题是,为了我的代码的可读性,我想使用字符串文字而不是数字。 这些应该在编译时转换为数字(无需额外的代码预处理)。

原则上这应该不是现在的问题,实际上以下似乎也有效:

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;

};

几乎:当然,哈希函数的使用并不是一个好的哈希函数。 (那里的89是由于我的测试代码:

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;
}

(请注意,哈希代替字符串文字的内部使用对函数的调用者是透明的。)

我的问题是:

  • 代码实际上是否符合我的要求?对代码进行定时表明,使用HashedStringfun_new)代替std::stringfun_old)时,它的运行速度要快得多。 (我正在使用g++ 4.8.2,选项-std=c++0x -O0。使用-O1似乎完全摆脱了循环?)

  • 我是否可以使用编译时哈希函数来实现此目的?我试过的所有其他(constexpr)哈希函数使得代码运行速度比以前慢(可能是因为constexpr在编译时没有在运行时进行评估。)我尝试使用这些:123

0 个答案:

没有答案