Идиоматический вектороподобный тип, параметризованный над индексом и типами значений

Существует ли идиоматический тип C ++ для непрерывного контейнера, который позволяет указывать оба типа значения (как std::vector а также std::array делать) а индекс / размер тип?

Я написал некоторый код, который будет манипулировать множеством массивов данных, но индексы разных массивов могут иметь разные семантические значения, и я хочу использовать систему типов, чтобы предотвратить случайное использование индекса в неверном контексте ,

Например, если я управляю коллекцией n шляпы и m автомобили, я могу дать каждой шляпе идентификаторы из 0 вплоть до n-1 и каждый автомобиль идентифицируется из 0 вплоть до m-1 и иметь различные массивы информации о шляпе и машине, но я бы не хотел случайно использовать идентификатор автомобиля, чтобы найти что-то в массиве информации о шляпе.

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 в пользовательском классе контейнера, который добавляет второй параметр.

1

Решение

Существует ли идиоматический тип C ++ для непрерывного контейнера, который позволяет указывать оба типа значения (как std::vector делает) а индекс / размер тип?

нет.


Здесь вы сталкиваетесь с типичным решением, которое мы должны принять, взвесив компромисс между затратами времени на разработку и использованием того, что STL уже предоставляет нам.

В первом случае вам придется потратить некоторое время, но надеяться получить лучшую производительность.

Во втором случае ваша структура данных готова к использованию, но вы можете потерять производительность w.r.t. структура данных, которую вы бы разработали.

Как Вам известно, std::unordered_map, обеспечивает постоянное время запроса, таким образом, я был бы вами, я бы продолжил с этой структурой данных (персонализируя ее столько, сколько я хочу, предоставляя настраиваемые объекты (например, CoryKramer предлагает хеширование в комментариях), а когда проект завершится, протестируйте производительность и искать горлышко бутылки этого Если это вызвано неупорядоченной картой, то — в зависимости от обстоятельств вашего времени, которые вы, возможно, не знаете точно сейчас — примите меры и разработайте пользовательскую структуру данных, которая при необходимости добьется цели.

3

Другие решения

Вы можете создать класс для этого, что-то вроде:

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.
0

По вопросам рекламы [email protected]