четверг, 28 ноября 2024 г.

[soft.dev.wtf] Мир сходит с ума... На примере маразма с "The Undefined Behaviour Question"

Просто зафиксирую эту историю здесь, т.к. мне она кажется показательной. Если кто не в курсе, то суть, как я ее понял, в том, что в комитет по стандартизации C++ было подано предложение под названием "P3403 The Undefined Behaviour Question". Кому-то из комитетчиков в названии увиделась аналогия с "еврейским вопросом" (Jewish Question) времен гитлеровской Германии. И автора предложения попросили поменять название. Он сперва раздумывал об этом, но потом решил оставить все как есть, т.к. придерживается мнения, что вопрос об undefined behaviour в языке программирования не имеет ничего общего с геноцидом по этническому признаку. После чего (как я понял) его предложение отказались пропускать через комитетскую бюрократию, а его самого подвергли обструкции.

Эта история всплыла на Reddit-е, в разделе /r/cpp, откуда была удалена, но осталась в другом разделе. А потом и сам автор предложения "The Undefined Behaviour Question" подробно изложил свою версию происходивших событий: First-hand Account of “The Undefined Behavior Question” Incident.

Ну что здесь остается сказать?

Сперва ветку master в git-е переименовали в main из-за того, что когда-то в США "master"-ом называли рабовладельцев, а сейчас git checkout master вызывает жуткие страдания у современных чернокожих программистов (ага, ага). Теперь вот это. Верной дорогой, товарищи. Прям как во времена СССР -- а нет ли в названии художественного произведения скрытой антисоветчины?

ИМХО, мир становится глобальным и чем больше это происходит, тем более диким выглядит то, как какая-то маленькая (в масштабах человечества) группа хер знает кого диктует всем остальным свои правила.

Это тем более дико на фоне того, что разработчикам из РБ и РФ обнуляют аккаунты на BitBucket-е, отказываются принимать от них pull request-ы, блокируют доступ к техническим ресурсам в Европе и США. Просто по географическому признаку: мол, если ты из РБ, то ты подлежишь обструкции. Просто потому что.

И если уж тут всплыла тема "еврейского вопроса", то нет ли здесь каких-то аналогий? Ну по типу навешивания "вины" просто по одному общему критерию -- раз из РБ, значит виноват в войне на Украине. Вроде бы где-то такое уже было? Что-то типа: ну, раз еврей, значит виноват в распятии Христа и пожирании невинных младенцев, и выпивании всей воды из крана.

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

PS. Если данный пост позволил кому-то рассмотреть во мне замшелого ватника, застрявшего в СССР, то поздравляю, ваши розовые очки в очередной раз треснули от столкновения с реальностью.

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

[prog.c++] Чего мне не хватило в boost::dynamic_bitset

Довелось немного попользоваться boost::dynamic_bitset. В принципе, отличная штука. И написана так, что можно заглянуть в потроха и понять что к чему. В общем, авторам решпект и уважуха.

Но я не был бы настоящим велосипедостроителем, если бы не отметил несколько моментов, которые могли бы упростить жизнь пользователю dynamic_bitset в моем сценарии.

Disclaimer: возможно, что-то из описанного ниже на самом деле в dynamic_bitset есть, просто я этого, несмотря на штудирование документации, не нашел 🙁 В таком случае прошу понять и простить... 😎

Во-первых, очень утомляет то, что для операций test и set нужно гарантировать, что индекс бита меньше текущего размера множества. Для меня это оказалось неудобно. Мне нужно фиксировать в bitset-е обработанные целочисленные индексы в диапазоне от нуля до N. Не всегда они идут последовательно, да и само N изначально неизвестно. Т.е. сперва мне нужно обработать, например, индекс 42, затем 24, затем 1, затем 100500.

Приходится перед вызовом set проверять, а есть ли i в bitset-е. Если нет, то сперва нужно сделать resize, а лишь затем вызывать set.

Аналогично, перед вызовом test нужно проверить, что i меньше size и только затем вызывать test.

В общем, неудобно. Было бы лучше, раз уж у нас dynamic_bitset, чтобы индексы больше или равные size обрабатывались должным образом без участия пользователя:

  • для set чтобы происходило автоматическое расширение множества;
  • для test чтобы возвращался false (ведь бита все равно нет, значит он точно не выставлен в единицу).

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

Из-за того, что операции AND/OR могут применяться только к множествам одного размера, приходится вручную разбираться с тем, какой кусок откуда вырезать, чтобы получить допустимые операнды.

Как по мне, было бы гораздо удобнее, если бы operator& сам бы определил результирующий размер итогового множества и выполнил AND только для фрагментов этого размера. Например, если мы делаем L & R, где L больше R, то имеет смысл выполнять AND только для первых R.size элементов из L.

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

В-третьих, идет в догонку к "во-вторых". Иногда нужно понять, а есть ли непустое пересечение между L и R. Т.е. мне не нужен точный результат пересечения, нужно просто понимать пусто ли такое пересечение или нет. Но если L и R имеют разные размер, то просто так я этого не узнаю. Мне сперва нужно получить два множества одинакового размера, потом уже для них делать intersect. Т.е. мне требуется создать новый dynamic_bitset, который нужен только для выполнения одного intersect-а и все.

Было бы круто, если бы был какой-то dynamic_bitset_view, похожий на std::string_view. Чтобы я мог в этот dynamic_bitset_view поместить только часть исходного dynamic_bitset-а. Причем чтобы при этом dynamic_bitset_view оставался бы легковесным объектом, который бы ничего никуда бы не копировал.

И тогда intersect вообще можно было бы делать не с исходными множествами L и R, а с их дешевыми фрагментами в виде dynamic_bitset_view.