查找表/索引到数组的数据类型

时间:2015-01-26 15:11:58

标签: c++ oop c++11

假设我有一个课程' Widget'。在我的应用程序中,我创建了很多Widgets(用于缓存局部性和其他原因)我保存在向量中。

为了有效查找,我想实现一个索引数据结构。为了这个问题,我们假设它是一个简单的查找表,从int索引到上述向量中的Widget元素。 我的问题是:查找表的内容应该是什么。 换句话说,我应该用哪种类型替换

中的问号
using LookupTable = std::vector<?>

我看到以下选项:

  • 引用(Widget&amp;,或者更确切地说,它必须是可分配的:reference_wrapper&lt; Widget&gt;)
  • 指针(小工具*)
  • 窗口小部件向量中的索引(size_t)
  • 指向Widget向量的迭代器对象(std :: vector&lt; Widget&gt; :: iterator)

在这些选项中,索引似乎是唯一一个不会被向量调整大小失效的选项。我实际上可以避免调整大小,但是,实现这样的查找表意味着对矢量实现进行假设,这似乎是不合理的“解耦设计”。观点出发

OTOH索引不是类型安全的:如果我从查找表中得到的东西是引用,我只能用它来访问相应的小部件。使用size_t值我可以进行无意义的操作,例如将结果乘以3.还要考虑以下两个签名:

void doSomethingWithLookupResult(Widget& lookupResult);
void doSomethingWithLookupResult(size_t lookupResult);

前者更具描述性。

总结:我可以将哪种数据类型用于查找表,以实现与向量实现和类型安全性的分离?

2 个答案:

答案 0 :(得分:2)

使用std :: vector :: size_type(不是size_t)。在大多数实现中,std :: vector :: size_type可能是size_t,但为了便携性和面向未来,我们会做得很好。

继续制作一个typedef: 使用WidgetIndex = std :: vector :: size_type;

这样看起来很合理:

void doSomethingWithLookupResult(WidgetIndex lookupResult);

这可以避免矢量调整大小问题,当你在你的问题中播放它时,最终会回来咬你。

不要玩像某些用户定义类型的游戏,比如tohava(非常聪明)建议,除非你打算在你的代码库中使用这个习惯用法。原因如下:

  • 你正在解决的问题(类型安全)是真实的,如果它是“免费的”,我们想要一个解决方案,但与其他机会相比,C ++程序员必须自己开枪,这不是'这个问题很重要。
  • 你会浪费时间。你的时间来设计课程,然后是你的代码库的每个用户的时间(包括你自己在几个月内忘记了实施后),这些用户会盯着那些代码并且不得不把它拼出来。
  • 在未来的某个时刻,你会躲过那个“有趣”的角落案例,我们现在都无法通过盯着这段代码看到它。

所有这一切,如果你要经常在你的代码库中使用这个习惯用法(你有许多存储在非常静态的向量或数组中的类),那么进行这项投资可能是有意义的。在这种情况下,维护负担分散在更多代码上,并且错误容器使用错误索引类型的可能性更大。

答案 1 :(得分:1)

您可以创建一个表示索引的类,该索引也包含类型信息(在编译时)。

#include <vector>

template <class T>
struct typed_index {
    typed_index(int i) : i(i) {}

    template <class CONTAINER>
    T &operator[](CONTAINER &c) { return c[i]; }
    template <class CONTAINER>
    const T &operator[](const CONTAINER &c) { return c[i]; }

    int i;
};

int main() {
    std::vector<int> v1 = {0};
    std::vector<const char *> v2 = {"asd"};
    typed_index<int> i = 3;
    int z = i[v1];
    const char *s = i[v2]; // will fail
}