在索引和值类型上参数化的惯用向量类型



是否有用于连续容器的惯用C++类型,允许您同时指定值类型(如std::vectorstd::array(和索引/大小类型?

我编写了一些代码来操作大量数据数组,但是各种数组的索引可能具有不同的语义含义,我想使用类型系统来防止我在错误的上下文中意外使用索引。

例如,如果我管理一组n帽子和m辆车,我可以为每个帽子 ID 提供从0n-1,每个汽车 ID 从0m-1,并具有各种帽子和汽车信息数组,但我不想意外地使用汽车 ID 在帽子信息数组中查找某些内容。

car_id model_t {0};
my::vector<hat_id, fabric> hat_materials { /*...*/ }
hat_materials[model_t]; // want this to be a compile error

现在,我在接受常量时间命中和使用std::unordered_map或花费一些开发时间将std::vector包装在添加第二个参数的自定义容器类中之间处于围栏状态。

是否有用于连续容器的惯用C++类型,允许您同时指定值类型(如std::vector(和索引/大小类型?

没有


您在这里面对的是我们必须做出的典型决定,权衡花费开发时间与使用STL已经提供给我们的时间之间的权衡。

在第一种情况下,您将不得不花费一些时间,但希望获得更好的性能。

在第二种情况下,您的数据结构已准备就绪,但您可能会失去本应开发的数据结构的性能。

如您所知,std::unordered_map,提供恒定的查询时间,因此我就是您,我会继续使用这种数据结构(通过提供自定义实体(例如 CoryKramer 建议在注释中进行哈希处理(来尽可能多地个性化它(,当项目完成时,测试性能并寻找它的瓶颈。如果它是由无序映射引起的,那么 - 根据你当时的情况,你现在可能还不知道 - 采取行动并开发一个自定义数据结构,如果需要,可以解决问题。

你可以为此创建一个类,如下所示:

template <typename IndexT, typename T>
class typed_vector
{
public:
typed_vector() = default;
typed_vector(const typed_vector&) = default;
typed_vector(typed_vector&&) = default;
typed_vector& operator=(const typed_vector&) = default;
typed_vector& operator=(typed_vector&&) = default;
template <typename ... U,
typename ... Ts,
std::enable_if_t<sizeof...(Ts) == 0
|| !std::is_same<std::decay_t<U>>::value,
typed_vector>* = nullptr>
typed_vector(U&& u, Ts&&...args) : mData(std::forward<Ts>(args)...) {}
typed_vector(std::initializer_list<T> ini) : mData(ini) {}

// The safe array subscript
const T& operator[](IndexT index) const {
return mData[static_cast<int>(index)];
}
T& operator[](IndexT index) { return mData[static_cast<int>(index)]; }
// ...
private:
std::vector<T> mData;
};

所以用

class hat_id
{
public:
explicit hat_id(int id) : id(id) {}
explicit operator int() const { return id; }
private:
int id;
};
// Equivalent for car_id

您可能有:

car_id model_t {0};
typed_vector<hat_id, fabric> hat_materials { /*...*/ }
hat_materials[model_t]; // Would be an error here.

最新更新