1.84K subscribers
3.27K photos
130 videos
15 files
3.55K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Forwarded from KMes
😁28🔥3
👍164💩3👎1
Апостиляга
👍4
Извините, я просто обязан это выложить
Forwarded from байборо♠️
🔥12👍1😁1
Forwarded from Agagagagagagagaggagagaggaggaggaga
Вот сейчас все орут с Яндекса, а они дождутся, когда все самые кривые места разойдутся мемасами по телеге, и отрефакторят все косяки, не вложив ни часа в анализ. Stonks, не иначе
🔥34😁5🤡2🌚1
👍9🤔3💩2
#prog #rust #rustreleasenotes

Вышла версия Rust 1.67.0! В этот раз заметных изменений не так уж и много. Вот полный список, если что. Как всегда, выпишу только то, что интересно мне.

▪️До стейбла докатилось изменение, о котором я уже писал: #[must_use] на асинхроных функциях теперь предупреждает не только о неиспользуемой футуре, возвращаемой функцией, но и о неиспользуемом возвращённом этой футурой значении.

▪️Ещё одно такое изменение: замена реализации MPSC-канала из std.

▪️И ещё одно такого рода: порядок дропа временных значений в цепочках из выражений, соединённых только && и соединённых только ||, теперь всегда слева направо, без специального отношения к первому подвыражению.

▪️И ещё одно: NonZero*::BITS.

▪️Трейт Sized стал коиндуктивным. Иными словами, если задача доказать ограничение T: Sized приводит к необходимости доказать это же самое ограничение, образуя цикл в логике, то вместо ошибки компилятор теперь выводит, что тип таки реализует Sized. На практике это означает, что рекурсивные типы, параметризованные типом индирекции, теперь нормально компилируются. Скажем, этот код не компилировался до этого изменения и компилируется после:

trait Allocator {
type Allocated<T>;
}

enum LinkedList<A: Allocator> {
Head,
Next(A::Allocated<Self>),
}

▪️Компилятор слегка поумнел в плане вывода типов для замыканий.

Остальное в подробных заметках о релизе.
👍11
Forwarded from я что-то �� и всё ����
👍22😁7
K P A C U B O
👍20
Forwarded from я что-то �� и всё ����
Оказывается, пайдантик может молча дропнуть создание класса, если немного накосячить с объявлением

Узнала я об этом при попытке проверить работу алиасов. Если базовая модель объявляет поле, а наследник переобъявит его через присваиваение pydantic.Field(alias=...), но *не* укажет тайпхинт, пайдантик дропнет вообще весь класс, как будто его и не было никогда

Причём достаточно одного такого поля, чтобы весь класс улетел в мусорку
🤣13👍4👎3😁1
Не плачь, ибо плачут только четырнадцатилетние девочки.

Ты взрослый мужчина — рыдай!
👍13🤮5😭5🔥1😐1
Forwarded from я что-то �� и всё ����
В вывеске часы работы указаны так
Зима: 8:00-21:00
Лето: 8:00-22:00

Теперь загадка жака фреско: как эта аптека работает весной и осенью? :blobcatgooglyholdingitsheadinitshands:
#prog #c #cpp #моё

Если вам вдруг понадобилось в рантайме выяснить, была ли ваша программа скомпилирована в режиме C или же C++, то вот непотокобезопасная функция, которая вернёт ответ в виде ноль-терминированной строки напрямую на большинстве систем:


char const* get_language() {
static char s[] = "C++\?";
s[sizeof s/sizeof'C'-sizeof'++'/2/sizeof'\?']=0;
return s;
}

Как же это работает? В отдельной переменной записывается строка, в нужную позицию записывается признак конца строки, а затем строка возвращается. Всем пока.

...

Нет, всё-таки, как это действительно работает?

Первая строка объявляет переменную s и присваивает ей значение. Переменная s статическая, чтобы возвращаемый указатель не становился висячим сразу после возврата из функции.

Строковые литералы в C и C++ являются массивами char-ов, включающими в себя неявно добавляемый на фазе трансляции терминирующий нуль-символ. s объявлена, как переменная типа char[]. Обычно тип в C(++) нужно выписывать целиком, но длину массива в объявлении переменной можно опустить, если её можно вывести из типа инициализирующего выражения — как в этом случае. Строка "C++\?" имеет четыре символа (четыре, потому что \? является escape-ом для ? (потому что триграфы)), поэтому с учётом конечного нуля получаем, что s имеет тип char[5].

Что же касается второй строки... Что ж, тут надо разбираться.

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

Во-вторых, в этой строчке sizeof применяется к, в частности, литералу символа. Чему равно значение этого выражения? Казалось, это должно быть 1, поскольку стандарт C прямо диктует (а стандарт C++ вторит), что sizeof(char) равен 1. Но! Тут мы применяем sizeof к литералу символа, и тут кроется одно из отличий между C и C++, делающее эту функцию возможной:

литерал символа имеет тип int в C и тип char в C++.

Тут возникает вопрос, какой же размер у int. Если вы программируете не под микроконтроллеры, то на вашей целевой системе тип int наверняка имеет размер 4 байта. Строго говоря, это не всегда верно, поскольку размер int является implementation defined, но это настолько распространённое и работающее на практике заблуждение, что после появления 64-битных систем размер int остался на них 4 байта. Не смотря на то, что int по замыслу является целым числом нативного для машины размера, смена размера int на 64-битных платформах до 8 байт сломала бы слишком много программ.

Итак, sizeof'C' и sizeof'\?' возвращает 4 для C и 1 для C++. sizeof s возвращают размер типа s. Для массива это размер в байтах. Так как s имеет тип char[5], sizeof s возвращает 5. Но вот что такое sizeof'++'? Нет, это не опечатка.

В-третьих, малоизвестный факт заключается в том, что в C и C++ в литерал символа можно записать больше одного символа, и называется это multi-character character literal. То, как именно эти литералы отображаются на численные значения, зависит от реализации — но нам это и не важно, потому что эти значения мы всё равно не используем. А вот что важно — так это то, что и в C, и в C++ такие литералы имеют тип int. Так что sizeof'++' возвращает таки 4.

С учётом изложенного выше, а также того, что оператор деления и в C, и в C++ является левоассоциативным, можно подсчитать, какие же получаются индексы в функции. Для C это

5/4 - 4/2/4 = 1 - 2/4 = 1

, поэтому присваивание записывает конец строки аккурат после первого символа C. Для C++ же

5/1 - 4/2/1 = 5 - 2/1 = 3

, потому присваивание записывает ноль после второго +.

В третьей строке строка возвращается, и из-за объявленного типа массив деградирует до указателя на его первый элемент. Признаком конца строки в C является ноль-символ, поэтому все функции стандартной библиотеки считают возвращаемое значение строкой "C" в C и "C++" в C++ соответственно. Как видите, всё очень просто.
👍16🤯11🔥1
Ну и напоследок о том, как можно эту функцию улучшить. В C++, в отличие от C, поддержка multi-character character literal является необязательной, поэтому конформная реализация C++ может попросту не скомпилировать эту функцию. Для того, чтобы улучшить переносимость между языками, можно убрать этот литерал и заменить sizeof'++'/2 на (sizeof'+'+sizeof'+').
👍3
😁174💩3👍1