Telegram Group Search
Channel photo updated
#compiler

День, когда умер CRTP 🫡

По исходникам проектов на C++ можно определять, примерно в какое время был написан код 👨‍🦳 В истории C++ был революционный стандарт C++11, еще чуть менее революционный C++20 (по убыванию используемости - concepts, ranges, coroutines, modules), и проходные между ними (C++14, C++17).

В C++23 есть единственная крупная фича, ради которой стоило его ждать - deducing this 😳 Единственное место, где нужно про него читать - пропозал в стандарт, там есть всё - мотивация, обоснование всех тонкостей дизайна, примеры использования, разбор всех корнер кейсов, и прочее. Все другие объяснения из интернета принципиально менее полны 📖 Я сюда не буду копипастить примеры, они есть в пропозале.

Long story short, в каждом методе используется неявный "нулевой" параметр this, эта фича добавляет возможность явно указать этот параметр, причем необязательно с исходным типом (можно заиспользовать шаблон). Это оказалось очень нужным - уменьшает дублирование методов, убирает необходимость в CRTP, позволяет удобнее рекурсивные лямбды, и прочее 😎

Конечно, у deducing this есть ряд drawbacks 🤷‍♂️
1️⃣Есть ряд спецэффектов по типу shadowing'а переменной базового класса (в пропозале они разобраны)
2️⃣ Методы становятся шаблонными со всеми вытекающими - Clang известен тем, что в отличие от MSVC не особо проверяет код шаблона до инстанциации
3️⃣ В коде начинается треш с категориями значений, нужно понимать разницу между auto, auto&&, decltype(auto), и специально добавили срань как std::forward_like.

Реализация deducing this наконец-то появилась в LLVM/Clang 18, который зарелизился 6 марта 😮 К сожалению, релиз получился всратым, и баги не пофикшены до сих пор 🚬 Поэтому его пока никто не использует.

Но уже сейчас можно изучать вопрос - как лучше всего подготовиться к использованию этой фичи и гарантировать, что все перестанут писать "по-старому"? 👦
В этом нам поможет libclang! Мы можем написать простые python-тесты на исходный код (о них писал тут🔍), и отлавливать устаревший код.

Первым делом нужно, чтобы в проекте генерировался compile_commands.json. Это простой список команд для компилятора, его описание тут, он нужен для многих вещей, например для автокомплита.
Его создание поддерживается в CMake, для этого в корневом CMakeLists.txt надо добавить:
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)


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

ПРОДОЛЖЕНИЕ В КОММЕНТАРИЯХ 🏃
Please open Telegram to view this post
VIEW IN TELEGRAM
#jostik #compiler

Обзор жостиков C++ 😎 (номер 0x00000002)

1️⃣ Сделай сам requires-clause для полей класса 😶

Шаблоны C++ развиваются в сторону упрощения - многое было сделано, чтобы избавиться от enable_if и ручной специализации шаблонов.

Одна из фичей - сейчас можно наложить trailing requires-clause на класс и на метод, чтобы ограничить их использование:
template<typename T>
requires std::copyable<T> && std::movable<T>
struct Blow {
void make_job()
requires (sizeof(T) > 100)
{ /* ... */ }
};

Логичным следующим шагом должно стать ограничение на поле класса.

Такое опциональное наличие поля было бы полезно везде, где из-за свойств шаблонной сущности меняется размер класса. Например делетеры в умных указателях (как std::unique_ptr). Или отсутствие поля "size", если он указан в шаблоне (как std::span).

Супер синтетический пример, как это должно работать у вектора, который на стеке или куче в зависимости от параметра:
template<typename T, std::size_t N = 0>
class JanusVector {
private:
// static vector, N is fixed
std::array<T, N> arr_ requires (N > 0);

// dynamic vector, N is not fixed
std::size_t size_ requires (N == 0);
T* data_ requires (N == 0);
};

// ...

int main() {
JanusVector<int, 228> vec1;
static_assert(sizeof(vec1) == 4 * 228);

JanusVector<int> vec2;
static_assert(sizeof(vec2) == 16);
}

Недавно мной была вкинута идея в разнорабочую группу по C++, пока без эффекта 🥱

Решил для прикола сделать реализацию этой фичи на Clang 👀
(Ссылки: как настроить сетап для clang, как создать свой keyword)

Дифф за пару вечеров получился не очень большим (он на gist.github.com), состоит из таких кусков:
1️⃣ В парсере разрешить парсить выражение trailing requires-clause после полей класса.
2️⃣ Сохранять это выражение в класс FieldDecl, вычислять его значение в методе isRequiresClauseSatisfied.
3️⃣ Добавить проверки в LayoutBuilder'е, чтобы не вкомпилировать storage под неудовлетворяющие поля.
4️⃣ Диагностировать обращения к неудовлетворяющим полям (создается ошибка компиляции).
5️⃣ Осторожно проинстанцировать выражение во время инстанциации шаблона 😠 Непроинстанцированные зависимые константные выражения невычисляемы!

Вот так можно делать proof of concept фичи 🥂 Это самый базовый пример, еще не рассмотрено несколько концептуальных вопросов, например:
1️⃣ Разрешить ли одинаковые имена у полей, если они никогда не скомпилируются вместе в одном классе?
2️⃣ Нужно ли помещать поле в скоуп выражения, для такого:
    // типа поле `kek_` скомпилится если у него будет метод `foo()`
T kek_ requires requires { kek_.foo(); };

3️⃣ Всякие мелкие баги, наподобии того что в реализации не запрещено брать адрес &Foo::kek у нескомпилировавшегося поля kek.

В КОММЕНТАРИЯХ ЕЩЕ ТРИ ЖОСТИКА C++ 🏃
Please open Telegram to view this post
VIEW IN TELEGRAM
#story

Обзор на работу в большой компании 💼

В начале этого года я покинул Яндекс, где проработал чуть больше 4 лет 👨‍🦳
Хотя там была ровная братва среди коллег и «интересные проекты»™️, я внял мудрости современного философа - «за деньги да» 😃 Но обо всем по порядку...

Часть1️⃣ Рассказ бывалого балабола

Я накидал субъективный обзор 😀 на плюсы и минусы
1️⃣ Hard skills
За несколько первых месяцев реальной работы в мощном темпе выучиваешь в разы больше, чем за годы «саморазвития» до этого 👦
За долгий срок работы можно порешать задачи из широкого спектра, испытать все виды инцидентов, и в целом это интересный опыт 🤡 Можно смотреть курсы ШАД, код крутых коллег, внутренние ресурсы.
Нельзя сказать, чтобы у каждого было супер крутое знание какого-либо языка - это не самоценность, а просто инструмент выполнения задачи. Нередко встречаются ржаки по типу как на этом скрине, что чела закинули в команду где пишут на Х и он тоже выучил Х за 21 день (можно догадываться про уровень понимания)👶
Компании не нужно, чтобы ты был rockstar - большие проекты делаются сотнями людей, и адекватный менеджмент ориентируется на их средний уровень, а также резервирует время под возможные переделки
Если же менеджмент неадекватный, то будут требовать сделать космолет за неделю, что будет не под силу даже Леннарту Поттерингу 😐
К вопросу о том - можно ли считать себя "ылитой", если ты работаешь в FAANG или под них косящих 😀 - имхо это звучит неуместно, когда речь идет о супер формализованном процессе найма workforce (результат каждого собеса это буквально true или false) с "good enough" компетенцией, чтобы закрывать стандартные таски. Так вижу.

2️⃣ Soft skills
Если есть желание, софт скиллы тоже неплохо прокачиваются. Хотя их можно качать бесконечно - если какой-то алгоритм или фичу можно выучить раз и навсегда, то взаимодействие с людьми это то, чему можно учиться всю жизнь 🤗
Обычный "работяга" - низшее звено пищевой цепочки. То, что он делает какие-то таски - это значит что топы определили направление, менеджеры поборолись за скоуп, а тимлид нарезал таски из глубокого знания codebase.

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

Это тот случай, когда "негативный опыт - тоже опыт". Так как многое завязано на человеческий фактор, комфортное пребывание во многом зависит от твоих коллег и еще намного больше от рукля.
За все время у меня было 5 руклей, со всеми я супер ровно сработался, кроме одного. Так оно работает - чтобы у тебя были задачи с высоким импактом и рост, необходимое условие чтобы рукль (и дальше по цепочке вверх) этого тоже хотели. Некоторое время я с ним промучался, но ничего не помогало и все было настолько плохо, что мне даже ставили встречу с HR с неприятным разговором 😵 Так что совет - лучше сразу уходить, если есть негатив с руклем, а не пытаться это исправить.
Я чуть не перешел к кенту в стартап, но по итогу просто ротировался в другой под-отдел и неплохо поработал в компании еще 1.5 года 💼

ПРОДОЛЖЕНИЕ В КОММЕНТАРИЯХ 📖
Please open Telegram to view this post
VIEW IN TELEGRAM
C++95
pic1.jpg
Please open Telegram to view this post
VIEW IN TELEGRAM
#jostik #compiler

Обзор жостиков C++ 😔 (номер 0b11)

На этот раз будет аж семь жостиков - три про DIY в Clang, одно про устройство Wireshark, одно с видео, и пара про идиомы C++ 📈 7️⃣ В данный момент это самый плотный набор жостиков.

1️⃣ [Clang] Сделай сам наследование в enum 🍷
У enum'ов в C++ нет наследования. Но это могло бы быть полезным в редких случаях, когда есть общий enum для всех кейсов, но в каких-то окружениях есть мелкие различия, которыми не хочется засорять общее место.

Пусть программа работает с большими ресторанами, куда отправляем запросы на доставку. С нашей стороны можно запросить новую доставку или отмену доставки (статус становится Adding/Cancelling и ждется ответ от сервера), после ответов от сервера статус становится Added/Cancelled/Delivered.
Большинство ресторанов не имеет возможности изменить адрес доставки (только отменять и создавать новую), но пусть какое-нибудь "Кафе Пушкинъ" 😬 так умеет, тогда неплохо бы иметь enum-наследник:
enum class DeliveryStatus : uint8_t {
Adding,
Added,
Cancelling,
Cancelled,
Delivered,
};
enum class CafePushkinDeliveryStatus : DeliveryStatus {
Moving,
};

(Планируется, что при изменении заказа статус меняется Added -> Moving -> Added)

Я попробовал придумать дизайн для наследования 🤔 Придумал такие правила:
1️⃣ У enum-наследника нумерация первой константы как будто она следует за последней константой родителя:
enum class First : short {
None, /* = 0 */
MovedPermanently = 301,
Found, /* = 302 */
SeeOther, /* = 303 */
};
enum class Second : First {
NotModified, /* = 304 */
UseProxy, /* = 305 */
BadRequest = 400,
Unauthorized, /* = 401 */
};
enum class Third : Second {
PaymentRequired, /* = 402 */
Forbidden, /* = 403 */
InternalServerError = 500,
};

2️⃣ enum-наследник наследует родительский underlying type транзитивно
static_assert(sizeof(First) == 2);
static_assert(sizeof(Second) == 2);
static_assert(sizeof(Third) == 2);
static_assert(std::is_same_v<std::underlying_type_t<First>, short>);
static_assert(std::is_same_v<std::underlying_type_t<Second>, First>);
static_assert(std::is_same_v<std::underlying_type_t<Third>, Second>);

3️⃣ enum-родитель может неявно кастоваться к своему enum-наследнику:
inline constexpr Third kFound = First::Found;

4️⃣ Скоуп enum-наследника включает в себя все символы enum-родителей - этот пример аналогичен прошлому:
inline constexpr Third kFound = Third::Found;

То есть lookup по Third::Found находит enum constant First::Found (имеет тип First), потом на нем делается implicit cast к типу Third 🪄

Сделал proof of concept в Clang - ссылка на дифф 😐
(Это базовый вариант - нет тестов, не супер красивый код, не рассмотрена возможность множественного наследования, и так далее...)

Код компилятора жесткий, есть много хаков чтобы например различать a ? new enum E : int{} от foo(a, enum E : int{}).
Также под флагами поддерживается нестандартный синтаксис, например можно писать enum E : int *p; что равносильно enum E : int; E *p; (прикол от microsoft)

ПРОДОЛЖЕНИЕ В КОММЕНТАРИЯХ 🏃
Please open Telegram to view this post
VIEW IN TELEGRAM
#quiz

Дикий тест по C++ с рофлами 😁

Давно ничего не писал, решил выкатить тест по 🅰️

Сделал его не баянистым и не мега жестким, а именно по своему личному рабочему опыту 💼
Он состоит из 50 вопросов, покрыты разные темы, но главное что почти везде за вопросом стоит реальная польза от знания ответов 🤔 Но это не точно

Проходите тест! https://www.group-telegram.com/QuizBot?start=WsPQdlYE 🔍 🤔
Please open Telegram to view this post
VIEW IN TELEGRAM
#offtop #essay

Löcherdämmerung (Гибель лохов) ⚰️

Решил написать небольшой обзор на современное общество 😉 Это не про C++, но тоже имеет отношение к делу. Уверен, что получилось достаточно злободневно

Все совпадения случайны, я не несу ответственность если вы узнали в чем-то себя 🤪 Посоветовал бы не принимать это всерьез, так как присутствует ржака

Читайте, может быть будет интересно 🧐
https://telegra.ph/L%C3%B6cherd%C3%A4mmerung-Gibel-lohov-10-20
Please open Telegram to view this post
VIEW IN TELEGRAM
C++95
sega_emulator.png
#longread #retro

Написал новую статью 📖 Это продолжение постов про m68k и про сегу.

Создаем эмулятор Sega Mega Drive на C++

В этой статье описано создание эмулятора 16-битной приставки Sega Mega Drive на C++ 🏃

Будет много интересного: эмуляция процессора Motorola 68000, реверсинг игр, графика на OpenGL, шейдеры, и многое другое. И все это на современном C++. В статье много картинок, можно хоть на них посмотреть 🔍
Please open Telegram to view this post
VIEW IN TELEGRAM
C++95
book1.jpg
#books #compiler

Обзор книги "Оптимизирующие компиляторы. Структура и алгоритмы" (2024 г.) 📚

Я вас категорически приветствую! Третьего дня, по совету проверенных камрадов, приобрел новую мегакнигу "Оптимизирующие компиляторы". Сразу же, задыхаясь от интереса, схватил книгу цепкими лапами и принялся читать.
Контент - мое почтение. Настоящей глыбой является Константин Владимиров. Даже моя, привыкшая к суровым алгоритмам башка, отказывалась принимать с первого захода. Совместными с ChatGPT усилиями дочитали книгу.
Ощущения - атас! С "dragonbook" не идет ни в какое сравнение. Кроме того, задания в конце глав заставляют сильно думать. Проходил так всю неделю. Решительно готов к новым контрибам в Clang/LLVM.
Многие дети тут увидят ненужные академические материалы. Тупым детям невдомек, что абстрактная математика и прикладные алгоритмы это разные вещи.
Книга отличная. Всем рекомендую к приобретению.
Все это, как водится, рецензия.



Работа компилятора разделяется на несколько больших кусков - условно "фронтенд" и "бэкенд" (но и внутри них своя иерархия 🖥)
95% того, о чем я писал (по хештегу #compiler и т.д.) относится именно к фронтенду компилятора.
На этом же уровне работают почти весь набор стандартных тулзов для C++ погромиста: clang-tidy (по AST), clangd (тоже по AST), clang-format (по аннотированным токенам) и т. д.
Во фронтенды компиляторов порог входа сравнительно низкий - без предварительной подготовки любой студент может почитать/покоммитить или даже создать свой фронтенд 👦

Другое дело - бэкенд компиляторов, там требуется более серьезная подготовка - с графами, линейной алгеброй, теорией алгоритмов, и прочим. Книга как раз сфокусирована на бэкенде, в основном высокоуровневом (в отрыве от инструкций конкретной машины).

Главы:
1️⃣ Тулчейны. Спидран по всем компонентам от грамматик до линкеров 🏃‍♂️
2️⃣ Введение в оптимизации. Древние алгосы про "анализ потока данных" и решение многих задач через "решетки", нужны для ввода в контекст.
3️⃣ Построение SSA. Что такое SSA и как его построить через "дерево доминаторов".
4️⃣ Базовые оптимизации для SSA. Крутые алгоритмы для "глобальной нумерации значений" и "устранения избыточных вычислений".
5️⃣ Цикловые оптимизации. Много алгоритмов для оптимизации циклов (как for и while).
6️⃣ Межпроцедурные оптимизации. Инлайн и де-инлайн функций, хвостовая рекурсия, девиртуализация, и т. д.
7️⃣ Разрушение SSA. Саморазрушение - вот что действительно важно. Перевод SSA в ассемблер, и лютое количество NP-полных задач чтобы это нормально сделать 😔

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

К алгоритмам есть информация - какие применяются в LLVM и/или GCC, есть много примеров на LLVM IR. Активно используется "динамическое программирование", "жадные алгоритмы", "union-find множества" и прочие дорогие сердцу.

Для каждого термина дается перевод на английский, тоже с мета-информацией. В частности есть доходчивое пояснение почему "graph cycle" переводится как "цикл" (и от него производные слова как "зациклиться" и т.д.), а "loop" тоже как "цикл" а не "луп" 🤔

Многие факты узнал впервые - например какие задачи компилятора решаемы (хотя бы за квадратичное время) а какие NP-полные, и компилятор их не делает решает приближенно 🚬

После прочтения книги в очередной раз понял, что не могу быть 100% уверенным, какой ассемблер сгенерирует компилятор 🤪 На эту тему есть крутой сборник фактов Common Misconceptions about Compilers.
Please open Telegram to view this post
VIEW IN TELEGRAM
C++95
plusich1.png
#jostik

Intro
Прошлой осенью на работе подарили брелок-"ремувку" с вышитыми логотипом компании и надписью "Born to win".
Посыл хороший - круто от рождения быть победителем в чем-то (например в беге или баскетболе).
Но этот предмет совсем не передает дух времени - ремувки это для путешествий, а сейчас они сильно затруднены, например маршрут Амстердам - Москва имеет две пересадки ⚰️

Решил сделать что-то более актуальное - по приколу сделал патчи на липучке, эти услуги предлагают десятки контор 😁 На фото их среда обитания:
1. Вот они слева направо
2. За несколько лет наиграл 800+ часов в хойке, тут мод "Kaiserredux" 😡
3. Образовываюсь во время долгих ребилдов всего репозитория 👩‍💻

Обзор жостиков C++
🤔 (номер 4️⃣)

1️⃣ Ужасы собеседований в HFT 😳
Иногда прохожу собесы в другие HFT - чтобы узнать что спрашивают по 👩‍💻 и какие условия. Сначала тебя находит очередная эйчарка и выпрашивает звонок под разными предлогами. Вообще, это guilty pleasure смотреть на их кринжово-смешные подкаты 😐

Потом наступает технический собес. Приятный техлид на том проводе предлагает перейти на "ты", и начать с короткого знакомства. Начинаем - я Евгений, мне 25, рост 192, <...>, люблю уравнения Максвелла, не люблю сырники. Какие планы на вечер? В планах провести собес.
- Напиши "single-producer single-consumer lock-free queue"

После этой простой задачи идет жесткое погружение в разные куски C++ - модель памяти, иерархия value category, особенности strict aliasing, чем хороши trivially-copyable в контейнерах и что там с лайфтаймами, и так далее.
Визави углубляется дальше, находятся вопросы которые заставляют реально думать... 🤔
- Для чего нужен std::hardware_destructive_interference_size?
- Расскажи какие ты знаешь протоколы когерентности кэшей в современных процессорах?

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

Вот такие собесы надо проводить, а не "напиши бинпоиск" и "разверни список" 😎

2️⃣ GDB pretty printer 🎨
Часто в GDB трудно понять что за значение у объекта 🤔 Так как выводятся значения структур "как есть" (грубо говоря, вместо вектора - адрес в памяти и размер), и без дополнительных команд ничего не понятно.

В таком случае надо использовать pretty printers - это код на 👩‍💻 Python, который вызывается со стороны GDB и может помочь в выводе более человекочитаемой инфы - трогая указатели, вызывая всякие функции, и так далее 😎
В первую очередь такие есть для реализаций std - например для libcxx.
Потом свой принтер можно сделать для каждой крупной кодовой базы - пример для LLVM где куча своих контейнеров.

Сейчас для рабочей кодовой базы есть свой pretty-printer для вывода значений таких объектов наших классов:
(1) strong types
(2) fixed-point числа
(3) json-объекты
(4) даты

3️⃣ Лютая скриптовая система с LLVM 💪
Недавно вышло видео с C++ Russia, где круто описано как можно сделать скриптовую систему 👍
Там скриптовый язык либо (1) на лету компилится в объектник и используется; либо (2) компилится с основной прогой для большей оптимизации.
Из "налогов" - диспетчеризация вызова, по сути вызов виртуальной функции.

Эта система - для игровых движков, но думаю в других местах тоже было полезно.
Например, писать рисечерам торговые стратежки проще на скриптовом языке, потому что С++ не их домен

4️⃣ Passkey Idiom 🔒
Читая один пропозал, увидел интересную идиому "Passkey", которую можно использовать как урезанный "friend class" (нарезает доступ по функциям).
Судя по гуглингу, вроде популярная вещь, но раньше нигде ее не видел.
Может пригодиться в кодовых базах, где овер9000 штук friend class.

5️⃣ Elvis Operator 🕺
"elvis operator" это запись:
a ?: b

что равносильно:
a ? a : b

Пригождается несколько раз в год 😎
Это поддерживается основными компиляторами с -Wnognu-conditional-omitted-operand.
Please open Telegram to view this post
VIEW IN TELEGRAM
2025/04/01 14:35:29
Back to Top
HTML Embed Code: