Я хочу иметь определенный тип std::vector
, который не может содержать больше элементов const int MAX_LENGTH
. Я понимаю, что я не могу переопределить не виртуальные функции std::vector
, которые мне нужно будет сделать, чтобы поместить проверку размера во все соответствующие функции-члены (например, assign
, push_back
... их так много), Самый очевидный способ сделать это - обернуть std::vector
в class
, который не гарантирует, что никакая операция не будет превышать максимальную длину. Но это кажется неуклюжим. Есть ли более элегантное решение, чем класс оболочки для ограничения размера std::vector?
Неинтрузивный способ принудительного ограничения размера на std::vector?
Ответ 1
Вы уверены, что сам вектор не может расти или что только потребители такого вектора должны ограничить размер аргументов? Если это последний, то просто assert(arg.size() <= MAX_LENGTH)
, где это необходимо, документируйте его и сделайте. В противном случае, читайте дальше.
A std::vector
может иметь неограниченный размер. Если вы ограничите этот размер, это не будет std::vector
. Таким образом, вы не можете публично выводить из std::vector
и ограничивать размер, не нарушая Принцип замены Лискова. Полученный класс по-прежнему является вектором, но не действует как один и не может использоваться как один, и такой интерфейс полностью запутает ваших пользователей, и компилятор не поймает серьезных ошибок использования, которые будут возникать. Это плохая идея.
Лучшее, что вы можете сделать, - это частное извлечение из вектора или наличие вектора в качестве члена, а также отображение всех векторных интерфейсов при обеспечении размера. Такой вектор не должен быть конвертирован в std::vector
, хотя, очевидно, вы можете разрешить его копировать или перемещать в std::vector
. Он по-прежнему будет работать так же хорошо, как и вектор, будет по-прежнему разрешать доступ через итераторы и т.д.
Мы говорим о очень маленьком классе, и его реализация просто должна следовать стандарту (или, по крайней мере, ссылка cpp), вы оставляете всю реальную работу частному std::vector
. Чтобы это не было неуклюжим, это единственный разумный способ сделать это.
Ответ 2
Так как С++ 11, пользовательским распределителям разрешено иметь состояние (ранее С++ 11, пользовательские распределители должны были быть без гражданства). Каждый контейнер С++, который использует специализированный распределитель, хранит его экземпляр.
Затем ваш распределитель может определить, выполнил ли он уже запрос на максимальный выделение, и выбросил иначе.
Ответ 3
#include <vector>
#include <string>
using namespace std;
template <typename T, typename A>
void add_or_throw(std::vector<T,A> &vec, int max, T value)
{
if (vec.size() < max)
{
vec.push_back(value);
}else{
throw length_error("vecor too beaucoup");
}
}
int main() {
std::vector<std::string> v;
add_or_throw(v, 2, string("hi"));
add_or_throw(v, 2, string("there"));
add_or_throw(v, 2, string("man!"));
return 0;
}