Открытый канал ID 70411625259198

Библиотека C/C++ разработчика | cpp, boost, qt

Реклама: t.me/tproger_sales_bot

Каналов в рубрике
17 332
Место этого канала
№ 5 168
Открыть рубрику →

Публикации за период

По реакциям

Поиск и вся лента — после бесплатной регистрации. Свои даты — по подписке; владелец канала видит их бесплатно. Сортировка по реакциям — по подписке. Зарегистрироваться

Загрузка…

Загружаем изображение…
🎯 IT раскололся: почему у одних специалистов будущее, а у других — тупик

Рынок делится пополам: продуктовые компании забирают себе лучших людей, AI-инфраструктуру и все деньги. Остальным достается борьба за крохи с демпингом и выгоранием. Это уже происходит. Читай, пока есть время что-то изменить.

👉 Читать...
Просмотры: 262
Перейти в пост Открыть в MAX Сообщить о неточности
📤 export: что именно вы отдаёте наружу?

Из модуля наружу видно только то, что помечено export. Всё остальное снаружи не видно — но это не «закрытость» уровня файла: у непомеченных сущностей модульное связывание, то есть их видят другие единицы трансляции того же модуля, просто не видит код, который подключает модуль. Это противоположность заголовкам, где в чужой код текстуально попадает вообще всё.

export module geometry;

export struct Point { double x, y; }; // открыто наружу

double dist(Point a, Point b); // скрыто снаружи,
// но доступно внутри модуля

export double length(Point p) { // открыто наружу
return dist(p, {0, 0});
}

Открыть наружу можно почти любую сущность: функции, типы, шаблоны, переменные, псевдонимы using.


🪐 Удобные формы записи



export { // блок экспорта
int foo();
int bar();
}

export namespace net { // только объявления ЭТОГО блока
void connect();
}

export import utils; // повторный экспорт: проброс
// чужого модуля дальше

❗️ export namespace открывает только то, что объявлено в этом блоке. Если позже снова открыть пространство имён net без export, новые имена наружу не уйдут.


❌ Ошибки

• export допустим только в единице, которая начинается с export module …;. В единице реализации (module geometry; без export) это ошибка компиляции
• export нельзя ставить на сущности в безымянном пространстве имён — у них внутреннее связывание
• функцию со static не открыть — она по определению локальна (внутреннее связывание)
• нельзя открывать что-либо из общей вступительной части модуля (того, что идёт до export module …;)
Просмотры: 164
Перейти в пост Открыть в MAX Сообщить о неточности
⚙️ TypeScript без V8: AOT-компиляция в нативный бинарник

В МойОфисе уперлись в санкционные ограничения Qt и медленную разработку UI на C++. Решение — компилировать TypeScript в натив напрямую, без браузера и интерпретатора.

• Фронтенд компилятора написан на самом TS и крутится в Node.js: переиспользуют парсер и AST от Microsoft

• Выход фронтенда — LLVM IR, дальше стандартный бэкенд LLVM и llc. По сути поток компиляции концептуально идентичен Clang

• Свой JS-рантайм (TSNative STD): базовые типы ECMAScript, GC, event loop — всё, что обычно даёт V8

• Сопоставление TS-вызовов с C++-символами идёт через .d.ts-декларации и nm: ищут по обычному имени, вставляют в IR mangled

Точка входа живёт на стороне C++: она инициализирует рантайм и дёргает единственный экспорт tsmain, в который слинкован весь TS-код как статическая библиотека (extern «C», с оглядкой на ABI)

👉 Статья
👉
Видео
Просмотры: 152
Перейти в пост Открыть в MAX Сообщить о неточности
⛄️ Почему find_package(Foo) ищет в двух режимах?

Многие думают, что find_package — это «одна команда, один поиск». На деле под капотом работает диспетчер двух разных механизмов, и путаница между ними — частая причина «package not found» при идеально установленной библиотеке.

🔍 Когда вы пишете find_package(Foo), CMake по умолчанию сначала запускает Module mode: ищет файл FindFoo.cmake сперва в CMAKE_MODULE_PATH, а затем во встроенных модулях самого CMake. Это скрипт-разведчик, который через find_path/find_library сам ищет заголовки и библиотеки на диске.

⚡️ Если модуль не найден, включается Config mode: CMake ищет FooConfig.cmake или foo-config.cmake — файл, который поставляет сам пакет и который точно знает, где что лежит.

❗️ Важно: это последовательный поиск с откатом, а не параллельный. И порядок можно перевернуть — с CMake 3.15 переменная CMAKE_FIND_PACKAGE_PREFER_CONFIG=ON заставляет сначала пробовать Config.

find_package(Foo) # сначала Module, потом Config
find_package(Foo CONFIG) # только Config mode
find_package(Foo MODULE) # только Module mode

❗️ Ключевое различие: FindFoo.cmake пишет кто угодно, кроме автора пакета — потребитель, сторонний разработчик или сами разработчики CMake (так поставляются FindThreads, FindOpenSSL и т.д.), и он угадывает расположение. А FooConfig.cmake поставляет сам автор библиотеки, и он обычно отдаёт готовые импортированные таргеты (Foo::Foo) с уже прописанными путями, флагами и зависимостями. Поэтому Config mode почти всегда надёжнее.

💡 На практике: если современная библиотека (через install(EXPORT)) не находится — проверьте не CMAKE_MODULE_PATH, а CMAKE_PREFIX_PATH, потому что искать нужно именно Config-файл.
Просмотры: 141
Перейти в пост Открыть в MAX Сообщить о неточности
🐛 Задача на выходные: есть ли проблема с deducing this?

C++23 «explicit object parameter» — мощь. Решили сделать zero-overhead геттер с идеальным пробросом самого объекта. На лайвах работает, в проде иногда мусор в строке.

struct Widget {
std::string name;
// отдаём name с тем же value-category, что и сам объект
auto&& title(this auto&& self) {
return std::forward<decltype(self)>(self).name;
}
};

const std::string& bad = Widget{"btn"}.title(); // ❓
std::println("{}", bad);

Задача: объясни, какой ровно тип выводится у title() при вызове на rvalue Widget, почему bad ссылается на уничтоженный объект, и где здесь lifetime extension НЕ срабатывает (и почему именно для deducing-this это особенно коварно). Как спроектировать API, чтобы компилятор ловил это?
Просмотры: 146
Перейти в пост Открыть в MAX Сообщить о неточности
🍬 EXPECT_DEATH не ловит исключение. Он запускает ваш код в отдельном процессе и ждёт его смерти

Если думал, что death-тест в GoogleTest — это просто проверка «упадёт или нет», то это не так. На деле фреймворк изолирует ваш код в дочернем процессе, дожидается его завершения и проверяет, что тот умер именно так, как вы ожидали. Сам тест-раннер при этом остаётся жив — в этом весь смысл.

💡Когда вы пишете EXPECT_DEATH(stmt, "regex"), фреймворк форкает текущий процесс. Дочерний выполняет stmt, родитель через waitpid() ждёт его завершения и анализирует статус выхода.

❓ Зачем вообще отдельный процесс? Потому что abort(), std::terminate или сработавший assert убивают процесс по-настоящему. Поймать это в том же процессе как исключение нельзя — управление уже не вернётся. Единственный способ протестировать смерть, не убив сам тест-раннер, — изолировать её в ребёнке.

EXPECT_DEATH(
{ std::abort(); },
".*"
);

❗️ Родитель и ребёнок после форка — два независимых адресных пространства (copy-on-write). Краш в ребёнке для родителя — просто ненулевой код возврата или сигнал.

❗️Death-тест — это не try/catch, это управляемое самоубийство подпроцесса. Если держать это в голове, перестаёшь удивляться, почему std::cout внутри блока ведёт себя странно.
Просмотры: 138
Перейти в пост Открыть в MAX Сообщить о неточности
Загружаем изображение…
🧵 Hazard pointers без воды

Разбор безопасного освобождения памяти в lock-free структурах: почему нельзя просто delete узел, который кто-то ещё держит.

• Гонка: X взял указатель на вершину и уснул, Y удалил узел, X читает по освобождённому адресу. UB
• ABA: аллокатор переиспользует адрес, CAS видит «тот же» указатель и возвращает мёртвое значение. Развал структуры
• Идея: поток публикует адрес в атомарный hp_ptr. Пока опубликован — узел не удаляют
• Удаление откладывается: кандидаты копятся в retired_list, реальный delete идёт позже, в фазе scan

Scan собирает все активные hp_ptr под shared_mutex, сортирует и бинарным поиском проверяет кандидатов. Нет в активных — deleter вызывается.

👉 Разбор
Просмотры: 144
Перейти в пост Открыть в MAX Сообщить о неточности
😊 doctest: тесты прямо рядом с кодом

Что если тесты можно писать в том же файле, что и реализацию, без потери скорости сборки? Именно эту идею продаёт doctest.

Это самый быстрокомпилируемый фреймворк из популярных: подключение заголовка почти не утяжеляет сборку. А с флагом DOCTEST_CONFIG_DISABLE все тесты вырезаются из релизного бинарника полностью.

Такой подход меняет привычку: проверку можно положить сразу под функцию, пока логика свежа в голове. Тест становится живой документацией, а не отдельным проектом в папке tests/.

int add(int a, int b) { return a + b; }
TEST_CASE("add") { CHECK(add(2, 2) == 4); }

✏️ Держите ли вы тесты отдельно от кода — или допускаете их соседство в одном файле?
Просмотры: 151
Перейти в пост Открыть в MAX Сообщить о неточности
☠️ Задача на выходные: std::thread, который убивает программу при выходе из функции

Маленькая безобидная функция создаёт std::thread, что-то делает и в конце — terminate() и аварийное завершение всего приложения. Без единого явного throw в коде.

void DoWork(bool earlyExitCondition) {
std::thread worker([]() {
Sleep(2000);
std::cout << "Done\n";
});

if (earlyExitCondition) {
return; // worker все ещё joinable!
}

worker.join();
}

Задача: объясни, почему деструктор std::thread вызывает std::terminate, если поток всё ещё joinable, и предложи паттерн, который защищает от этого на всех путях выхода из функции, включая исключения.
Просмотры: 164
Перейти в пост Открыть в MAX Сообщить о неточности
Вся лента — после бесплатной регистрации
ВКонтакте Телеграм Одноклассники
Избранное в datool.ru

Следите за каналом в личном кабинете

Зарегистрируйтесь в datool.ru, чтобы добавить канал «Библиотека C/C++ разработчика | cpp, boost, qt» в избранное и отслеживать его показатели.

Зарегистрироваться
Для владельцев каналов

Подтвердите свой канал

Войдите или зарегистрируйтесь в datool.ru, затем добавьте нашего бота в канал по инструкции в личном кабинете. После проверки владения замок исчезнет и вам станет доступно управление каналом.

Войти или зарегистрироваться

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти