Библиотека C/C++ разработчика | cpp, boost, qt
34K subscribers
2.13K photos
67 videos
16 files
4.46K links
Все самое полезное для плюсовика и сишника в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/d6cd2932

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5bac324c8ba6dcaa1ad17

#WXSSA
Download Telegram
👁 C++ Ranges. Требования к диапазонам

C++20 ввёл концепты — способ формально выразить требования к типам. В Ranges они используются повсеместно, поэтому важно понимать, что говорят сообщения об ошибках и почему один алгоритм принимает vector, а другой требует что-то большее.

//  Не скомпилируется
std::list<int> lst = {3, 1, 2};
std::ranges::sort(lst);
// Ошибка: list не удовлетворяет концепту random_access_range

// vector удовлетворяет random_access_range
std::vector<int> vec = {3, 1, 2};
std::ranges::sort(vec);

// У list есть собственный метод сортировки
lst.sort();



🍋 Иерархия концептов

Концепты выстроены в цепочку наследования: каждый следующий добавляет требования к предыдущему. sized_range и viewable_range — ортогональны иерархии, они не зависят от позиции в цепочке.

range
└── input_range
└── forward_range
└── bidirectional_range
└── random_access_range
└── contiguous_range



‼️ Зачем нужен viewable_range?

Ещё есть viewable_range, он тоже не входит в иерархию. Нужен, так как не любой range можно безопасно обернуть во view. Если передать временный объект, итератор получит висячий указатель — объект уничтожается раньше, чем его успевают использовать. Концепт viewable_range запрещает это на уровне компилятора.


🍩 Проверка концептов в compile-time

Тут всё просто, нужно обернуть проверку в static_assert и сразу, на этапе компиляции, получишь ошибку если что-то не так:

static_assert(std::ranges::random_access_range<std::vector<int>>);
static_assert(!std::ranges::random_access_range<std::list<int>>);
static_assert(std::ranges::bidirectional_range<std::list<int>>);


🐸 Продолжение следует...

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#константная_правильность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🙏1
😎 Топ-вакансий для C++ разработчиков за неделю

Senior Rendering engineer C++ в 3D Карту — от 350 000 и до 400 000 ₽ Удалёнка/Гибрид (Санкт-Петербург, Москва)

C-разработчик (Storage) — от 350 000 и до 450 000 ₽ Удалёнка

Инженер-программист С++ — от 250 000 и до 300 000 ₽ Офис/Удалёнка (Москва)

✍️ Еще больше топовых вакансий — в нашем канале C++ jobs

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#буст
2😁1
This media is not supported in your browser
VIEW IN TELEGRAM
😢1
🗓 В следующий вторник (28.04) в 19:00 встречаемся в онлайне.

Тема:
Как эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токены


В кружке Кирилл рассказал, какие именно подходы будем разбирать.

👉 Занять место на вебинаре
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1😁1
🔩 Vtable изнутри: что компилятор прячет за virtual

Автор статьи разбирает внутреннее устройство виртуальных таблиц согласно Itanium C++ ABI — тому самому стандарту, которому следуют GCC и Clang на большинстве платформ.

Ключевые моменты статьи:

• почему vptr указывает не на начало vtable, а со смещением
• как расположены записи в vtable при множественном и виртуальном наследовании
• что такое construction vtable (VTT) и когда она используется

Основной фокус — не просто «как работает virtual», а что происходит на уровне байтов и ассемблера, когда компилятор реализует динамическую диспетчеризацию.

Если вы когда-либо видели в стектрейсе vtable for ClassName и не понимали, что это — самое время разобраться.

👉 Статья

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#линкер_рекомендует
👍101
🌳 Деревья в алгоритмах — быстрый гайд по иерархическим структурам

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

👉 Что такое дерево:

Это структура данных, где элементы связаны иерархически: есть корень → ветки → листья.

Примеры из жизни:
— файловая система
— DOM в браузере
— организационные структуры

Базовые типы деревьев:
— Бинарное дерево — у каждого узла максимум 2 потомка
— Бинарное дерево поиска (BST) — слева меньше, справа больше
— Сбалансированные деревья (AVL, Red-Black) — держат высоту под контролем
— Trie — для строк и префиксов

📍 Навигация: ВакансииЗадачиСобесы

Библиотека питониста

#буст
👍8😁1
🌿 userver 3.0: крупное обновление open source C++ фреймворка от Яндекса

userver — асинхронный фреймворк для микросервисов и highload-систем, который используется в production внутри Яндекса и доступен в open source. Вышла версия 3.0 — с большим количеством прикладных улучшений для backend-разработки.

✏️ Что добавили в релизе

• Более 2500 изменений и доработок
• Chaotic — генерация однотипного кода по схемам данных
• userver easy — быстрый запуск микросервиса с возможностью дальнейшего масштабирования
• Улучшения по потреблению RAM и CPU
• Дополнительные инструменты диагностики и отказоустойчивости

⚡️ Почему релиз важный

Во многих C++ backend-проектах основные затраты времени уходят не на бизнес-логику, а на инфраструктурную обвязку: HTTP, базы данных, логирование, асинхронность, observability, graceful shutdown, retries, metrics.
Здесь это уже собрано в production-ready стек, который прошёл нагрузку в сервисах масштаба Яндекса.

🐸 Что особенно полезно

Chaotic закрывает одну из самых затратных задач — поддержку boilerplate-кода вокруг DTO, схем и сериализации. А userver easy снижает порог запуска новых сервисов и ускоряет прототипирование без необходимости собирать каркас проекта с нуля.

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#cpp #backend #opensource
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
🍿 std::views::filter — ленивая фильтрация в C++20

Адаптеры std::views::* — главный инструментарий Ranges. Каждый из них создаёт новое «представление» существующих данных без копирования. Сегодня разберём views::filter.


🌸 Базовое использование

#include <ranges>
#include <vector>
namespace views = std::views;

std::vector<int> nums = {1, -2, 3, -4, 5, -6};

auto positives = nums | views::filter([](int x) { return x > 0; });
// Итерация даёт: 1, 3, 5


Ничего не копируется — positives это просто обёртка поверх nums, которая позволяет удобно обрабатывать его элементы.


🍪 Цепочка фильтров

auto is_even = [](int x) { return x % 2 == 0; };

auto result = nums
| views::filter([](int x) { return x > 0; }) // 1, 3, 5
| views::filter(is_even); // нет чётных → пусто


Фильтры можно комбинировать в произвольную цепочку. Вычисление происходит лениво — только в момент итерации.


👻 Композиция с views::transform

Достаточно просто ограничить обработку только тех элементов, которые хотим обработать:

auto squares = nums
| views::filter([](int x) { return x > 0; })
| views::transform([](int x) { return x * x; });
// Итерация даёт: 1, 9, 25



🍙 Материализация в вектор

View — это не контейнер. Чтобы получить std::vector необходимо явно дать указание, что мы хотим привести результат к вектору:

// C++23
auto vec = nums | views::filter(is_even)
| std::ranges::to<std::vector>();

// C++20
std::vector<int> vec(result.begin(), result.end());



🌱 Pipe-синтаксис vs явный тип

Синтаксис в виде pipe удобе, но если необходимо (например, для шаблонов), то можно пользоваться диапазонами как типами/объетами. Обе записи идентичны:

auto v1 = nums | views::filter(is_even);
auto v2 = std::ranges::filter_view{nums, is_even};



❗️ Ловушка: dangling view

// UB — вектор уничтожен после точки с запятой
auto bad = std::vector{1, 2, 3} | views::filter(is_even);

// Правильно — храните источник данных отдельно
std::vector<int> data = {1, 2, 3};
auto ok = data | views::filter(is_even);



🐸 Продолжение следует...

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#константная_правильность
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥21
🛠 Бесплатные курсы от MIT

Университеты дают алгоритмы, OS, компиляторы — но не учат пользоваться инструментами, с которыми разработчик проводит большую часть рабочего времени. MIT решили это исправить.

• Курс покрывает shell, профилирование, отладку, git и упаковку кода — всё то, что обычно осваивается методом тыка в первые годы работы.
• В версии 2026 добавлен модуль по agentic coding: как встраивать AI-инструменты в реальный рабочий процесс, не теряя контроль над кодом.
• Отдельный акцент на качестве кода — тема, которая в академической среде почти не появляется
• Лекции доступны на YouTube, материалы открыты, есть переводы на 17 языков включая русский.


🍬 The Missing Semester of Your CS Education (eng)

🍬 Пропущенный семестр курса по компьютерным наукам (рус)


✏️ Что из этого списка вы осваивали самостоятельно, а не на работе или учёбе?


📍 Навигация: ВакансииЗадачиСобесы

Библиотека питониста

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
5😁1
🩹 Задача на выходные: const-итерация по Range

#include <ranges>
#include <vector>

void process(const auto& view) {
for (auto x : view) { (void)x; }
}

int main() {
std::vector<int> data = { 1, 2, 3, 4, 5 };
auto pred = [](int x) {
return x % 2 == 0;
};

auto filtered = data | std::views::filter(pred);
process(filtered); // не компилируется
}


Объясни механизм: почему begin() const невозможен в принципе, а не по недосмотру комитета.


📍Навигация:
ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#междусобойчик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍206❤‍🔥203🤩202🥰191😁1
🔥 База по ИИ-агентам от научного сотрудника Сколтеха и НИУ ВШЭ

Знакомьтесь, Екатерина Трофимова. Кандидат компьютерных наук, ресерчер в Центре ИИ Сколтеха и лаборатории LAMBDA. Она объединяет глубокую академическую экспертизу и практику: знает, как ИИ-системы устроены «под капотом» и как встроить их в реальные проекты (в т.ч. для Т-банка).

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

🛠 Стек и фреймворки:

DSPy — алгоритмическая оптимизация промптов (вместо ручного подбора слов).

Semantic Kernel и LangMem — инструменты для управления сессионной и долгосрочной памятью.

MCP (Model Context Protocol) — новый стандарт от Anthropic для подключения агентов к вашим БД и локальным файлам.

📖 Документация, которую нужно знать:

Anthropic Prompt Caching — как кэшировать контекст и радикально резать косты на API.

OpenAI Agents SDK / Cookbook — лучшие практики работы с памятью.

Augment — платформа для оптимизации работы ИИ-агентов и контроля токенов.

🔬 Хардкорные статьи и препринты (на выходные):

Lost in the Middle — почему LLM «слепнут» на длинных текстах и забывают середину контекста.

How Do Coding Agents Spend Your Money? — куда улетает бюджет при работе автономных кодинг-агентов.

MemGPT — архитектура операционной системы для LLM с иллюзией бесконечной памяти.

InjecAgent / AgentSentry — всё о безопасности и защите агентов от инъекций в промпты.

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

🎁 Акция в честь старта продаж!

Прямо сейчас при покупке Инженерного трека вы получаете полный доступ к материалам курса «Разработка ИИ-агентов» в подарок.

👉 Забрать 2 курса по цене 1 и начать обучение
❤‍🔥214🔥202🥰198👍189😁1
⚙️ Хотим сделать одну вещь — собрать нормальный список людей, за которыми реально следит C++ сообщество

C++ — язык с историей. И у него есть живое сообщество людей, которые двигают его вперёд — через доклады, статьи, открытый код и просто посты в сети.

⁉️ Хотим узнать, кого читаете именно вы

Не «обязательный список» — а реальный срез того, за кем следит наш канал. Может, откроем друг другу что-то новое.

📎 Формат простой:

• Имя
• Где (YouTube, блог, X, GitHub...)
• Почему именно он/она

👇 Пишите, собирём в отдельный пост

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#междусобойчик
296👍289💯257🥱3😁1
🍴 Умные указатели в Qt: почему new никуда не делся

Современный C++ давно говорит «забудь про new». Qt говорит «подожди». Статья разбирает, почему иерархическая модель фреймворка и RAII плохо живут вместе.

QObject с родителем удаляется деструктором родителя. Если при этом он ещё и под unique_ptr — получишь double free: умный указатель не знает, что объект уже мёртв.

QWeakPointer как аналог слабой ссылки здесь не поможет — он работает только с QSharedPointer, который в Qt-иерархии использовать нельзя. Для этого есть QPointer<T>, который подписывается на destroyed() и обнуляется сам.

sender() возвращает QObject* — объект, которым уже кто-то владеет. Оборачивать результат в умный указатель — значит воевать с фреймворком.

• В QML ситуация хуже: JS GC может удалить переданный из C++ объект без родителя, не предупредив. Краш случится через непредсказуемое время. Спасает только QQmlEngine::CppOwnership или явный родитель.

QScopedPointer имеет смысл перед std::unique_ptr в одном конкретном случае — QScopedPointerDeleteLater для объектов вроде QNetworkReply, которые нельзя удалять немедленно. В остальном std-аналоги легче и лучше интегрируются с внешними библиотеками.


💡 Решение предлагается в статье в виде правила:

• есть родитель -> сырой указатель,
• нет родителя -> QScopedPointer или std::unique_ptr
• нужно следить за чужим объектом -> только QPointer
• бизнес-логика без QObject -> чистый STL.


✏️ Статья

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#линкер_рекомендует
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥223👍210❤‍🔥208203🥱1
🍿 Иерархический FSM (HFSM)

FSM (конечный автомат) — это не rocket science. Это просто способ явно описать: «в каком состоянии я нахожусь» и «что происходит при событии X». Пригодится везде: парсеры протоколов, UI-логика, игровые NPC, сетевые соединения.

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

HFSM позволяет группировать состояния. Применяется в игровых движках (вложенные состояния NPC), UI-фреймворках, протоколах с retry-логикой.

🧋 Реализация

#include <iostream>
#include <functional>
#include <map>
#include <optional>

enum class State { Idle, Running, Paused, Active, Stopped };
enum class Event { Start, Pause, Resume, Stop };

// Состояние может иметь родителя — тогда необработанные события
// делегируются вверх по иерархии
struct StateNode {
std::optional<State> parent;
std::function<void()> onEnter;
std::function<void()> onExit;
};

class HierarchicalFSM {
State current_;
std::map<State, StateNode> nodes_;
std::map<std::pair<State,Event>, State> transitions_;

public:
explicit HierarchicalFSM(State init) : current_(init) {}

void defState(State s,
std::optional<State> parent = std::nullopt,
std::function<void()> enter = {},
std::function<void()> exit = {}) {
nodes_[s] = {parent, std::move(enter), std::move(exit)};
}

void addTransition(State from, Event ev, State to) {
transitions_[{from, ev}] = to;
}

bool process(Event ev) {
// Ищем переход от текущего состояния вверх по иерархии
std::optional<State> search = current_;
while (search) {
auto it = transitions_.find({*search, ev});
if (it != transitions_.end()) {
exitState(current_);
current_ = it->second;
enterState(current_);
return true;
}
// Поднимаемся к родителю
auto nodeIt = nodes_.find(*search);
search = (nodeIt != nodes_.end()) ? nodeIt->second.parent
: std::nullopt;
}
return false; // переход не найден
}

State state() const { return current_; }

private:
void enterState(State s) {
if (auto it = nodes_.find(s); it != nodes_.end())
if (it->second.onEnter) it->second.onEnter();
}
void exitState(State s) {
if (auto it = nodes_.find(s); it != nodes_.end())
if (it->second.onExit) it->second.onExit();
}
};

int main() {
HierarchicalFSM fsm(State::Idle);

// Active — виртуальный родитель для Running и Paused
fsm.defState(State::Active);
fsm.defState(State::Idle);
fsm.defState(State::Running, State::Active,
[] { std::cout << "[ENTER] Running\n"; },
[] { std::cout << "[EXIT] Running\n"; });
fsm.defState(State::Paused, State::Active);
fsm.defState(State::Stopped, std::nullopt,
[] { std::cout << "[ENTER] Stopped\n"; });

fsm.addTransition(State::Idle, Event::Start, State::Running);
fsm.addTransition(State::Running, Event::Pause, State::Paused);
fsm.addTransition(State::Paused, Event::Resume, State::Running);
// Stop работает из любого Active-состояния
fsm.addTransition(State::Active, Event::Stop, State::Stopped);

fsm.process(Event::Start);
fsm.process(Event::Pause);
fsm.process(Event::Stop); // делегируется к Active -> Stopped
return 0;
}


❗️ Добавь состояние — и оно автоматически наследует все переходы родителя. Не нужно дублировать Stop в каждое дочернее состояние.


✏️ Используешь FSM в продакшне?


🔥 Успейте на курс по ИИ-агентам! До 30 апреля осталось всего 4 места.
👉 Занять место по ссылке


📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#шаблонный_код
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥52🙏2
🍙 views::transform — ленивые преобразования в C++20

Если views::filter решает, какие элементы обработать, то views::transform — во что их превратить. Никакого копирования: это такая же ленивая обёртка над данными.

🌸 Базовое использование

#include <ranges>
#include <vector>
#include <string>
namespace views = std::views;

std::vector<std::string> words = {"hello", "world", "cpp"};

// Получаем длины слов
auto lengths = words | views::transform([](const std::string& s) {
return s.size();
});
// При итерации: 5, 5, 3


Лямбда применяется к каждому элементу в момент итерации — ни раньше, ни позже.

🍪 Трансформация с изменением типа

transform не обязан возвращать тот же тип. Из string можно получить size_t, из doubleint, из структуры — одно из её полей:

// Верхний регистр (#include <cctype>)
auto upper = words | views::transform([](std::string s) {
for (char& c : s) c = std::toupper(c);
return s;
});
// При итерации: "HELLO", "WORLD", "CPP"


Обратите внимание: здесь s принимается по значению — это намеренная копия, которую мы модифицируем.


🍀 filter + transform — классика

Главная сила адаптеров — в их цепочке. Сначала отсеиваем ненужное, потом преобразуем то, что осталось:

struct Employee {
std::string name;
double salary;
bool is_active;
};

std::vector<Employee> employees = {
{"Алиса", 80000, true},
{"Борис", 95000, false},
{"Виктор", 72000, true},
{"Галина", 110000, true},
};

// Имена активных сотрудников с зарплатой выше 75 000
auto high_earners = employees
| views::filter([](const Employee& e) { return e.is_active; })
| views::filter([](const Employee& e) { return e.salary > 75000; })
| views::transform([](const Employee& e) { return e.name; });

for (const auto& name : high_earners) {
std::cout << name << "\n"; // Алиса, Галина
}


Весь конвейер ленив: ни одна лямбда не вызывается, пока не начнётся итерация.


🌱 pipe-синтаксис vs явный тип

auto v1 = words | views::transform([](const std::string& s) { return s.size(); });
auto v2 = std::ranges::transform_view{words, [](const std::string& s) { return s.size(); }};



🍙 Материализация в вектор

transform_view — не контейнер. Чтобы получить std::vector, нужно явно материализовать:

// C++23
auto vec = words | views::transform([](const std::string& s) { return s.size(); })
| std::ranges::to<std::vector>();

// C++20
std::vector<size_t> vec(lengths.begin(), lengths.end());



Ловушка: несовпадение типа возврата

// UB — возвращается ссылка на временный объект
auto bad = words | views::transform([](const std::string& s) -> const std::string& {
std::string upper = s;
return upper; // dangling reference!
});

// Правильно — возвращаем по значению
auto ok = words | views::transform([](const std::string& s) {
std::string upper = s;
for (char& c : upper) c = std::toupper(c);
return upper;
});



🐸 Продолжение следует...

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#константная_правильность
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰3👍2🤔2🥱1
GCC 16: наконец-то читаемые ошибки компилятора

C++ и нечитаемые ошибки компилятора — классика жанра. GCC 16 делает шаг в сторону человекочитаемости.

• Иерархическое отображение диагностик теперь включено по умолчанию (в GCC 15 это был экспериментальный флаг).

• Несовпадение сигнатур больше не требует детективного расследования. Если параметр 3 — void* вместо const void*, компилятор ткнёт в конкретную строку.

SARIF-вывод вырос: вложенные logicalLocations с полным путём namespace → class → function.

• Появился -fdiagnostics-add-output=experimental-html — HTML с подсветкой кода и визуализацией стека.

-fanalyzer наконец понимает C++: exception handling и NRVO реализованы. Честно: на большой кодовой базе анализатор тихо капитулирует. Для проода — ещё не подходит.

👉 Полный разбор

🤖 Осталось 4 места на курс по ИИ-агентам. Набор закрывается 30 апреля.
🔗 Успеть на обучение

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#свежак
👍3👏2🙏1🥱1