пятница, 4 октября 2024 г.

[prog.c++] Использование одного аргумента шаблона (aka Traits) вместо нескольких

В догонку ко вчерашнему посту про недостающую функциональность в std::vector.

Понятное дело, что std::vector уже не сможет получить каких-то дополнительных шаблонных аргументов, потому что это поломает кучу существующего кода.

Кстати говоря, есть у меня ощущение, что в любом C++ном проекте, который писали обычные люди, вроде меня, а не монстры, вроде Девида Вандервуда или Барри Ревзина, куча кода поломается, если в std::vector начнут использовать собственные аллокаторы. Поломается потому, что код написан в стиле:

void do_something(const std::vector<int> & data) {...}

И даже шаблонный код написан вот так:

template<typename T>
void do_something(const std::vector<T> & data) {...}

а не вот так (хотя бы вот так):

template<typename T, template Allocator>
void do_something(const std::vector<T, Allocator> & data) {...}

Впрочем, это уже совсем другая история...

Но если пофантазировать?

Есть, на мой взгляд, достаточно простой способ сделать параметры шаблона расширяемыми в будущем, но без изменения списка этих самых параметров.

Это подход на базе Traits. Уже не помню, откуда про него узнал, не удивлюсь, если из книг Александреску. Но подход уже старый и мы, например, применяем его в RESTinio.

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

Например, для std::vector это могло бы выглядеть так:

template<typename T>
struct default_vector_traits {
  using allocator = std::allocator<T>;
};

template<typename T, typename Traits = default_vector_traits<T> >
class vector {...};

И если бы со временем нам бы потребовалось добавить в шаблон std::vector еще один параметр (тот же нужный мне growth_policy), то это можно было бы сделать не меняя списка параметров для std::vector:

struct default_vector_growth_policy {
  std::size_t operator()(std::size_t current_capacity) const {
    // Код примерный, прошу помидорами не бросаться ;)
    return (current_capacity > 1 ? static_cast<std::size_t>(capacity * 1.5) : 2);
  }
};

template<typename T>
struct default_vector_traits {
  using allocator = std::allocator<T>;
  growth_policy = default_vector_growth_policy;
};

template<typename T, typename Traits = default_vector_traits<T> >
class vector {...};

И если бы мне захотелось использовать с векторами собственную политику роста емкости, то мне бы потребовалось всего лишь:

struct my_growth_policy {
  std::size_t operator()(std::size_t current_capacity) const {...}
};

template<typename T>
struct my_vector_traits : public std::default_vector_traits<T> {
  using growth_policy = my_growth_policy;
};

using my_int_vector = std::vector<int, my_vector_traits<T>>;

Понятное дело, что шаблоны классов контейнеров из стандартной библиотеки на Traits уже не перевести. Но если вы пишите свои библиотеки шаблонных классов (особенно собственных типов контейнеров, неприведихоспади!), то имеет смысл подумать о применении подхода с Traits.

четверг, 3 октября 2024 г.

[prog.c++] В std::vector не хватает вот какой штуки...

Интересно, много ли C++ программистов задумывается о том, а как растет std::vector, когда мы в него добавляем элементы через push_back и не имеем возможности сделать предварительно reserve?

А ведь рост размера std::vector может существенным образом повлиять на расход памяти.

Предположим, что реализация std::vector в вашей стандартной библиотеке использует коэффициент 1.5 для увеличения размера вектора. Т.е. вы делаете push_back в полный вектор и опа! Ваш вектор увеличился в полтора раза. Была емкость на 1000 элементов, а стала на 1500. А использоваться оттуда будет 1001.

А если реализация стандартной библиотеки использует коэффициент 2, то дела еще хуже.

Сильно негативно это начинает проявляться на векторах размером в миллион-два-три и т.д. Если у вас в программе таких векторов не один и не два, то вы с удивлением для себя сможете обнаружить, что в этих векторах где-то 1/5 или 1/4, а то и 1/3 объема не занято. Что в сумме может дать десятки мегабайт впустую потраченной памяти.

Чтобы этого не происходило приходится вручную контролировать размер и емкость вектора и, опять же, вручную дергать reserve перед push_back-ами.

А то, что делается вручную, легко забыть или же сделать неправильно 😣

Поэтому мне лично не хватает возможности задать для std::vector какую-то собственную политику роста. Что-то типа:

struct my_growth_policy {
  [[nodiscard]] std::size_t operator()(std::size_t current_capacity) {
    return ... // здесь какие-то вычисления.
  }
};

using my_vector = std::vector<my_data, std::allocator<my_data>, my_growth_policy>;

Тогда не пришлось бы вручную контролировать емкость перед каждым push_back-ом.

Но, боюсь, в стандартном std::vector такого не будет никогда.

среда, 2 октября 2024 г.

[life.cinema] О фильмах про "Чужого"

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

Мне очень нравятся первые три фильма, каждый из них шедеврален. Хотя первый "Чужой" на мой взгляд, самый слабый из них. Но тут обязательно нужно делать поправку на время, в которое он был снят. Полагаю, в конце 1970-х сложно было сделать лучше. А вот "Чужих" и "Чужой-3" пересматриваю регулярно. Причем чем старше становлюсь, тем больше мне нравится именно третья часть.

По хорошему, на этом стоило бы и остановиться. Но бабло, как известно, побеждает, так что имеем что имеем.

Четвертый фильм был бы говном, если бы не несколько но. Во-первых, он очень красиво и атмосферно снят. Во-вторых, там есть несколько шикарных моментов. Например, как чужие реагируют на "обучение" и как они находят способ выбраться наружу. Самый же гениальный из этих моментов -- это как Рипли заходит в лабораторию, в которой ее клонировали, и видит результаты предшествующих неудавшихся попыток. Так что есть в нем что-то хорошее. Но это хорошее точно не относится к финалу.

"Прометей" и "Завет" просто говно говна. Вначале "Прометея", когда люди высадились на неизвестную планету без скафандров, стало понятно, что ничего хорошего ждать не приходится, что и подтвердилось. Так что лучшее, что можно сделать с "Прометеем" и "Заветом" -- это забыть про их существование.

Недавний "Ромул" вроде как возвращается к истокам. Но мне он кажется вторичным, поскольку подобное мы уже видели в четвертом фильме. Даже антропоморфный мутант в конце, с которым пришлось бороться в последние мгновения перед возможной катастрофой.

Не знаю, будут ли еще продолжения, полагаю, что будут. Вопрос только когда.

И, предположу, что там обязательно главным борцом с очередным чужим окажется девушка или молодая женщина. Ну такой сильный женский персонаж, который все превозмогёт и всех победит. Как же может быть иначе? ;) Что делает потенциально продолжение немного предсказуемым.

Еще, как бы это странно не звучало, мне зашел "Чужой против Хищника". Конечно же кино специфическое и по своему уровню ему далеко как до первых трех "Чужих", так и до первого "Хищника". Но зато качественно сделанное. Как мне показалось с любовью и уважением к двум исходным франшизам. Жаль что вторая часть этого противостояния оказалась отстоем, хотя этого и можно было ожидать.

вторник, 1 октября 2024 г.

[life.cinema] Очередной кинообзор (2024/09)

Традиционный обзор отсмотренных за минувший месяц фильмов. Традиционно в начале каждого из списков то, что понравилось больше, а в конце то, на что можно не тратить свое время. Но в этот раз, в принципе, почти все упомянутые фильмы и сериалы можно обойти стороной. Не случилось ничего, чтобы реально понравилось и что я мог бы порекомендовать.

Фильмы

Чужой: Ромул (Alien: Romulus, 2024). Ну хоть отказались от прямого продолжения маразматической линии "Прометея" и "Завета", хотя и есть отсылки к этим двум говношедеврам. В целом мне показался похожим на четвертую часть. И не понравился он мне тем же, чем и четвертая часть -- очередной попыткой скрестить чужого и человека и получить неведомого мутанта. В целом же любители вселенной "Чужого" вполне могут посмотреть, это явно лучше "Прометея" и "Завета".

Восхитительно! (Délicieux, 2021). Этот фильм можно посмотреть просто ради красивой картинки. Временами работа оператора выше всяких похвал, хочется поставить воспроизведение на паузу и рассматривать кадр как картину. Сама же история простенькая и, как мне кажется, откровенно сказочная.

Ускорение (Slingshot, 2024). Хорошо сделанное кино. Но не могу сказать, что мне понравилось, т.к. с некоторых пор не люблю открытые финалы и недосказанность.

Одинокие волки (Wolfs, 2024). Противоречивые впечатления. С одной стороны фильм из категории тех, что мне, в принципе, нравятся. Но не понравился, т.к., во-первых, герои не вызывают сопереживания. И вообще нет ощущения реальности происходящего. Ну типа есть два крутых героя, круче которых, сразу понятно, нет никого. Поэтому ничего с ними произойти не может. И остается только ждать когда случится какой-то очередной прикол. Во-вторых, как-то создатели не озадачились внятным объяснением происходящего, так что я в итоге не понял кто кого куда и зачем отправлял. В-третьих, некоторые моменты в фильме выглядели надуманными и нелепыми. В общем, кино с такими двумя актерами не оправдывает ожиданий.

Ловушка (Trap, 2024). Отличная игра Джоша Хартнетта в фильме, где все происходящее выглядит каким-то откровенным маразмом.

Мистер Блейк к вашим услугам (Complètement cramé, 2023). Не понял что это было. Возможно, я еще слишком молодой, а кино рассчитано на 65-75 летних зрителей. Но выглядит это все как ужасно рафинированная сказочка-сказочка, в которой нет ни одного нормального персонажа, не говоря уже о хоть каком-либо отношении к реальности.

Ворон (The Crow, 2024). Затянуто и скучно.

Оставь мир позади (Leave the World Behind, 2023). Редкая муть. Посмотреть можно разве что если вам почему-то захотелось выкинуть два часа из своей жизни.

Воровка (2023). Халтурная халтура. Смело можно проходить мимо.

Сериалы

Охотничьи псы (Sayanggaedeul, первый сезон, 2023). Я бы сказал, что это сериал для подростков, настолько глуповаты там главные герои. Но для подросткового кино оно излишне жесткое местами. Так что даже не знаю как классифицировать: для взрослых слишком наивное, для детей слишком кровавое.

Точка ноль (первый сезон, 2024). Сплошное разочарование. Ожидал напряженного фильма про борьбу с неизвестным вирусом, но как раз ни напряжения, ни борьбы, ни ожидания глобального коллапса из-за вырвавшейся на свободу болезни в сериале не обнаружилось. Зато рассказали про сына-алкоголика зав.лаборатории, про бывшего любовника главной героини, про отголоски каких-то разборок из 90-х годов и пр. муть. В общем, категорически не рекомендую.

Не смог досмотреть

Властелины воздуха (Masters of the Air, первый сезон, 2024). Снято, конечно же, красиво. Вероятно сцены воздушных боев сделаны мастерски с максимальным сохранением исторических деталей и стремлением к достоверности. Но вот не торкает и все. Скучно и ничего с этим не смог поделать. С трудом дождался завершения второй серии и решил не продолжать.

План Б (Plan B, первый сезон, 2024). Когда во второй серии окончательно прояснилось вокруг какой идеи крутится все происходящее на экране, то стало неинтересно. А когда в третьей серии начались какие-то странные действия со стороны персонажей и приплюсовалась современная толерантная повесточка, то вообще желание продолжать просмотр пропало окончательно.

Криминальное прошлое (Criminal Record, первый сезон, 2024). Сперва раздражал откровенные непрофессионализм главной героини, а потом еще и возникло ощущение, что конфликты между некоторыми героями создают искусственно и на ровном месте, без должной мотивации. Плюс традиционное для сериалов неспешное развитие событий. В общем, в какой-то момент возникло желание прекратить просмотр и забыть про это "кино".