Существует ли идиоматический тип 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
в пользовательском классе контейнера, который добавляет второй параметр.
Существует ли идиоматический тип C ++ для непрерывного контейнера, который позволяет указывать оба типа значения (как
std::vector
делает) а индекс / размер тип?
нет.
Здесь вы сталкиваетесь с типичным решением, которое мы должны принять, взвесив компромисс между затратами времени на разработку и использованием того, что STL уже предоставляет нам.
В первом случае вам придется потратить некоторое время, но надеяться получить лучшую производительность.
Во втором случае ваша структура данных готова к использованию, но вы можете потерять производительность w.r.t. структура данных, которую вы бы разработали.
Как Вам известно, 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.