【问题标题】:Dynamic hash->class tag动态哈希->类标签
【发布时间】:2010-07-23 18:01:19
【问题描述】:

我有:

const unsigned int hash_1 = 0xaf019b0c;
const unsigned int hash_2 = 0xf864e55c;  
const unsigned int hash_3 = 0xfaea8ed5;

哈希来自自动生成的标头。这些散列与标签 1、2、3 间接关联。标签通过简单的编译时生成的 id 与类关联。这样我就可以GetTag<Class1>() 并获得 Class1 的 int-tag。

我的目标是简化 hash->tag 关联。最好这应该是编译时生成和 O(1) 访问时间。在这种情况下,内存不是问题。我不能使用任何第三方软件。

我尝试了以下方法:

template<uint32 t>  size_t GetTagByHash() { return 0; }

具体实现如下:

template<> size_t GetTagByHash<hash_1>() { return GetTag<Class1>(); }

但是这种实现很难使用,因为如果我有一个局部变量 uint32 my_hash; 编译器无法确定它在编译时具有什么值,那么编译器就无法解析 @987654326 的正确实现@调用。

【问题讨论】:

  • 您的意思是要杀死您的模板吗?另外,hash_N 是否像您显示的那样单独命名? (我假设这些类不是。)
  • 已编辑以修复标记问题,因此 GetTagByHash 上的模板现在可见。
  • hash_N 只是我输入的名称——它们是唯一的名称。杀死我的模板?我不确定你的意思。

标签: c++ templates hash tagging compile-time


【解决方案1】:

据我了解,您的问题是如何使用运行时值和编译时值进行此查找。

你真的有两个问题。首先,您想使用什么算法来进行查找,其次,您如何告诉 C++ 来实现它?

要使用的算法在某种程度上是一个不明显的问题;您有一个有效随机数的列表,并且您想在该列表中查找某些内容并返回关联的标签。可能您想要某种哈希表,但首先,我将展示一些更简单的示例——对于少量哈希可能更好:一个简单的 O(N) 查找,伪代码:

if i = N return tag_N
else if i = N-1 ...
...
else if i = 1 return tag_1
else return tag_0

现在,您如何告诉 C++ 执行此操作?您必须创建所有哈希标签的列表,以及执行此操作的说明。这是一个简单的方法:

template<int i> struct lookup
{
  int result(int j) { return 0; }
};

const unsigned int hash_1 = 0xaf019b0c;
template<> struct lookup<1>
{
  int result(int j)
  {
    if (j == hash_1)
      return GetTag<Class1>();
    return lookup<0>::result(j);
  }
};

const unsigned int hash_2 = 0xf864e55c;
template<> struct lookup<2>
{
  int result(int j)
  {
    if (j == hash_2)
      return GetTag<Class2>();
    return lookup<1>::result(j);
  }
};

等等。然后,最后,您可以拥有

int hash_lookup(int j)
{
  return lookup<last_hash_number>::result(j);
}

不过,写出所有这些相同的定义是一件很痛苦的事情,因此最好让 C++ 来做——而且,要做到这一点,您需要以一种可以迭代的方式定义哈希。让我们这样做:

template<int> struct hash_tag {
  static const int value = 0;
  typedef type void;
};

#define SET_HASH(I, VALUE, CLASS)   \
template<> struct hash_tag<(I)>     \
{                                   \
  static const int value = (VALUE); \
  typedef type (CLASS);             \
}

SET_HASH(1, 0xaf019b0c, Class1);
SET_HASH(2, 0xf864e55c, Class2);
SET_HASH(3, 0xfaea8ed5, Class3);

// Define a general recursive lookup struct.
template<int i> struct lookup
{
  int result(int j)
  {
    if (j == hash_tag<i>::value)
      return GetTag<hash_tag<i>::type>;
    return lookup<i-1>::result(j);
  }
};

// Make sure the recursion terminates.
template<> struct lookup<0>
{
  int result(int) { return 0; }
};

然后,你像以前一样使用它。

现在,让我们回到第一个问题——您实际上想使用什么算法来进行查找?这种迭代 O(N) 查找的优点是它易于编程,并且它不需要在运行时对任何数据结构进行任何初始化——您只需调用它即可。但是,如前所述,它是 O(N)。另一种选择是使用std::map 对象;您可以使用类似的递归定义在运行时对其进行初始化,然后使用它。这可能看起来像这样:

// Make a typedef to save some typing.
typedef std::map<unsigned int, size_t> Map_type;
typedef std::pair<unsigned int, size_t> Map_value;

// Define a recursion to add hashes to the map.
template<int i> struct add_hash
{
  void add(Map_type& hashmap)
  {
    hashmap.insert(
      Map_value(hash_tag<i>::value, 
                GetTag<hash_tag<i>::type>));
    add_hash<i-1>::add(hashmap);
  }
};

// Make sure the recursion terminates.
template<> struct lookup<0>
{
  void add(Map_type&) {}
};

// Now, create a class to initialize the std::map and do lookup.
class Hash_lookup
{
  Hash_lookup() { add_hash<last_hash_number>(map_); }
  int result(unsigned int j) { return map_[j]; }
private:
  Map_type map_;
}

就我个人而言,我可能会将其与您的 GetTagByHash&lt;&gt; 想法结合起来,并为 Hash_loop 提供我所描述的“运行时计算结果”函数,以及采用模板的“编译时计算结果”函数参数而不是函数参数。但是,一般来说,这是进行运行时查找的基本思想——您将要查找的值放入一组模板类中,您可以在编译时对其进行递归迭代,然后使用该递归迭代来定义查找函数或初始化可用于进行查找的运行时结构。

【讨论】:

  • 您的答案非常好,尽管它似乎遇到了与我相同的问题 - 我必须实现动态哈希映射才能使索引查找正常工作。我想这个问题可以更好地描述为如何将运行时哈希转换为编译时哈希。既然我已经阅读了您的帖子,我知道这可能是不可能的,除非您在递归中指出。我在想也许将数据预编译到表中是将其变为 O(1) 的唯一方法?
  • 我找到的简单解决方案,它并不是真正的最佳解决方案,但它有点工作:#define ADD_HASH_PROPERTY(HASH, PROPERTY) case HASH: return GetTag(); size_t GetTagByHash(uint32 _hash) { switch(_hash) { ADD_HASH_PROPERTY(hash1, Class1); ADD_HASH_PROPERTY(hash2, Class2); ADD_HASH_PROPERTY(hash3, Class3); } 返回 0; }
猜你喜欢
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2020-10-07
  • 2016-04-23
  • 2015-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多