Полезная статья про автоматическую проверку архитектуры C++-проекта!
Автор разбирает инструмент archcheck, который помогает описать правила зависимостей между модулями и проверять, что кодовая база не превращается в хаотичный клубок include-связей.
В статье автор показывает:
• как описывать допустимые зависимости между частями проекта
• как находить нарушения архитектурных границ
• почему такие проверки полезно запускать в CI
📣 C++ Ready | #статья
Автор разбирает инструмент archcheck, который помогает описать правила зависимостей между модулями и проверять, что кодовая база не превращается в хаотичный клубок include-связей.
В статье автор показывает:
• как описывать допустимые зависимости между частями проекта
• как находить нарушения архитектурных границ
• почему такие проверки полезно запускать в CI
Продолжай читать на Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤5🔥4😁1
Считаем размер папки через std::filesystem!
Иногда нужно быстро понять, сколько места занимает директория. Например, перед очисткой, анализом или проверкой файлов.
В C++17 для обхода файловой системы есть
Подключим нужные заголовки:
Для удобства заведём namespace:
Функция будет принимать путь к папке:
Сначала заведём счётчик байт:
Теперь рекурсивно обойдём директорию:
Нас интересуют только обычные файлы. Папки и ссылки можно пропустить:
Размер файла добавляем в общий счётчик:
После обхода возвращаем результат:
Вызов может выглядеть так:
В реальном коде стоит помнить про права доступа. Если часть файлов нельзя прочитать, можно использовать перегрузки с
📣 C++ Ready | #практика
Иногда нужно быстро понять, сколько места занимает директория. Например, перед очисткой, анализом или проверкой файлов.
В C++17 для обхода файловой системы есть
std::filesystem.Подключим нужные заголовки:
#include <filesystem>
#include <iostream>
Для удобства заведём namespace:
namespace fs = std::filesystem;
Функция будет принимать путь к папке:
std::uintmax_t dir_size(const fs::path& root) {Сначала заведём счётчик байт:
std::uintmax_t total = 0;
Теперь рекурсивно обойдём директорию:
for (const auto& entry : fs::recursive_directory_iterator(root)) {Нас интересуют только обычные файлы. Папки и ссылки можно пропустить:
if (!entry.is_regular_file()) continue;
Размер файла добавляем в общий счётчик:
total += entry.file_size();
После обхода возвращаем результат:
return total;
}
Вызов может выглядеть так:
auto bytes = dir_size("logs");
std::cout << bytes << "\n";В реальном коде стоит помнить про права доступа. Если часть файлов нельзя прочитать, можно использовать перегрузки с
std::error_code, чтобы программа не падала на первом недоступном каталоге.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5🔥3
Разбираем std::format и форматирование строк!
std::format помогает собирать строки без цепочек operator<< и без ручной склейки. Форматирование становится ближе к шаблону, где видно итоговую форму текста.
В этой шпоре собраны format, format_to, formatted_size, format_to_n, std::print, chrono formatting и custom formatter.
📣 C++ Ready | #шпора
std::format помогает собирать строки без цепочек operator<< и без ручной склейки. Форматирование становится ближе к шаблону, где видно итоговую форму текста.
В этой шпоре собраны format, format_to, formatted_size, format_to_n, std::print, chrono formatting и custom formatter.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍4❤3🤝1
Собираем потокобезопасную очередь на C++!
Нужно передавать задачи между потоками так, чтобы один поток мог добавлять элементы, а другой спокойно ждать новые данные без активного цикла и лишней нагрузки на CPU.
В этой задаче:
Такую основу можно использовать для worker-пула, фоновой обработки логов, очереди событий или простого producer-consumer сценария.
📣 C++ Ready | #задачу
Нужно передавать задачи между потоками так, чтобы один поток мог добавлять элементы, а другой спокойно ждать новые данные без активного цикла и лишней нагрузки на CPU.
В этой задаче:
• храним queue под mutex
• будим ожидающий поток через condition_variable
• достаём элементы через wait_and_pop
Такую основу можно использовать для worker-пула, фоновой обработки логов, очереди событий или простого producer-consumer сценария.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍8🔥4
Напоминалка по lambda expressions в C++!
Например, capture by reference позволяет лямбде работать с внешней переменной напрямую, capture by value сохраняет копию значения, а mutable даёт менять захваченную копию внутри лямбды.
На картинке собраны основные приёмы работы с lambda expressions. Есть захваты по ссылке и по значению, init capture, immediately invoked lambdas, mutable lambdas, generic lambdas, perfect forwarding и возможности C++20.
Сохрани, чтобы не потерять!
📣 C++ Ready | #ресурс
Например, capture by reference позволяет лямбде работать с внешней переменной напрямую, capture by value сохраняет копию значения, а mutable даёт менять захваченную копию внутри лямбды.
На картинке собраны основные приёмы работы с lambda expressions. Есть захваты по ссылке и по значению, init capture, immediately invoked lambdas, mutable lambdas, generic lambdas, perfect forwarding и возможности C++20.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍6🔥3
Разбираем std::variant: как хранить разные типы без unsafe union!
std::variant помогает описывать значения, которые могут быть одним из нескольких заранее известных типов. Это удобно для парсеров, состояний, команд, ошибок и ответов API: данные остаются типобезопасными, а компилятор помогает не забыть обработать нужные варианты.
📣 C++ Ready | #шпора
std::variant помогает описывать значения, которые могут быть одним из нескольких заранее известных типов. Это удобно для парсеров, состояний, команд, ошибок и ответов API: данные остаются типобезопасными, а компилятор помогает не забыть обработать нужные варианты.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤5👍3
Зачем в C++ помечать важные результаты через [[nodiscard]]?
Иногда функция возвращает значение, которое нельзя просто проигнорировать: статус операции, ошибку, открытый ресурс, результат валидации.
Например:
Код компилируется, но результат потерян. Если сохранение не удалось, программа может продолжить работу так, будто всё нормально.
Для таких случаев есть атрибут [[nodiscard]]:
Теперь компилятор предупредит, если результат вызова проигнорировали:
Правильнее явно обработать результат:
Особенно полезно помечать функции, которые возвращают объект ошибки:
Или результат проверки:
Если результат действительно нужно проигнорировать, лучше показать это явно:
Так сразу видно, что разработчик сделал это осознанно, а не случайно.
📣 C++ Ready | #совет
Иногда функция возвращает значение, которое нельзя просто проигнорировать: статус операции, ошибку, открытый ресурс, результат валидации.
Например:
bool save_config() {
return write_file("config.json");
}
save_config();Код компилируется, но результат потерян. Если сохранение не удалось, программа может продолжить работу так, будто всё нормально.
Для таких случаев есть атрибут [[nodiscard]]:
[[nodiscard]]
bool save_config() {
return write_file("config.json");
}
Теперь компилятор предупредит, если результат вызова проигнорировали:
save_config(); // warning
Правильнее явно обработать результат:
if (!save_config()) {
std::cerr << "Config was not saved\n";
}Особенно полезно помечать функции, которые возвращают объект ошибки:
[[nodiscard]]
std::optional<User> find_user(int id);
Или результат проверки:
[[nodiscard]]
bool is_valid_token(std::string_view token);
Если результат действительно нужно проигнорировать, лучше показать это явно:
(void)save_config();
Так сразу видно, что разработчик сделал это осознанно, а не случайно.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍7🔥3