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

Idiomatic vector-like type parameterized over index and value types

是否有用于连续容器的惯用 C++ 类型,可让您同时指定值类型(如 std::vectorstd::array 所做的那样)和 index/size 类型?

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

例如,如果我正在管理 n 顶帽子和 m 辆汽车的集合,我可以为每顶帽子提供从 0n-1 的 ID并且每辆汽车 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 包装在自定义容器 class 之间犹豫不决第二个参数.

Is there an idiomatic C++ type for a contiguous container that lets you specify both the value type (as std::vector does) and the index/size type?

没有.


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

第一种情况需要花费一些时间,但希望获得更好的性能。

在第二种情况下,您的数据结构可以使用,但您可能会损失性能w.r.t。你会开发的数据结构。

如您所知,std::unordered_map 提供恒定的查询时间,因此我就是您,我会继续使用此数据结构(通过提供自定义实体(例如 CoryKramer 建议hashing in the comments),等项目完成后,测试一下性能,寻找它的bottleneck,如果是无序map导致的,那么——看你当时的情况,您现在可能还不完全了解 - 采取行动并开发一个自定义数据结构,如果需要的话,它可以解决问题。

您可以为此创建一个 class,例如:

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.