Вызов callable объектов (функции, лямбды, member функции) требует разного синтаксиса. Но можно унифицировать вызовы с помощью std::invoke.
// Разный синтаксис для разных типов
func(); // функция
obj.method(); // метод
(obj.*ptr_to_member)(); // указатель на метод
lambda(); // лямбда
// Единый синтаксис для всех callable
std::invoke(func);
std::invoke(&Class::method, obj);
std::invoke(lambda);
std::invoke(ptr_to_member, obj);
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🤔2🔥1😢1
⚡️ Фича дня: [[likely]]/[[unlikely]] (C++20)
🔥 Проблема:
Компилятор не знает, какие ветки кода выполняются чаще, что влияет на производительность.
✏️ Решение:
Атрибуты помогают компилятору оптимизировать предсказание переходов.
❌ До:
✅ После:
Применение:
• Обработка ошибок в системном коде
• Оптимизация горячих путей в циклах
• Улучшение производительности критических секций
💡 Помогают ли вам атрибуты в оптимизации?
Библиотека C/C++ разработчика
#буст
Компилятор не знает, какие ветки кода выполняются чаще, что влияет на производительность.
Атрибуты помогают компилятору оптимизировать предсказание переходов.
if (error_code != 0) {
handle_error(); // редкий случай
} else {
normal_processing(); // частый случай
}
if (error_code != 0) [[unlikely]] {
handle_error(); // компилятор оптимизирует как редкий случай
} else [[likely]] {
normal_processing(); // оптимизируется как частый случай
}
Применение:
• Обработка ошибок в системном коде
• Оптимизация горячих путей в циклах
• Улучшение производительности критических секций
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍11🔥3
🧨 Портирование C++ проектов: подводные камни архитектурных различий
💡
❗️ Ключевые моменты лекции:
• скрытые баги из-за изменения размеров указателей при переходе с 32-bit на 64-bit
• проблемы с SIMD-инструкциями при портировании с SSE (x86) на Neon (ARM)
• необходимость полного переписывания ассемблерного кода под новую архитектуру
Основной фокус — практические проблемы портирования X-Ray движка («Сталкер») на консоли и методы их решения через статический анализ кода.
Особенно актуально для разработчиков игровых движков и системного ПО, где производительность критична.
Вы узнаете, что код, который «просто работает», может содержать десятки скрытых UB, которые проявятся только при смене платформы — и найти их без специальных инструментов практически невозможно.
👉 Видео
Библиотека C/C++ разработчика
#буст
💡
Ростислав Михеев
в своей лекции на UNIGINE Open Air 2025
разобрал реальные кейсы портирования игровых движков и выделил критические моменты для C++ разработчиков.❗️ Ключевые моменты лекции:
• скрытые баги из-за изменения размеров указателей при переходе с 32-bit на 64-bit
• проблемы с SIMD-инструкциями при портировании с SSE (x86) на Neon (ARM)
• необходимость полного переписывания ассемблерного кода под новую архитектуру
Основной фокус — практические проблемы портирования X-Ray движка («Сталкер») на консоли и методы их решения через статический анализ кода.
Особенно актуально для разработчиков игровых движков и системного ПО, где производительность критична.
Вы узнаете, что код, который «просто работает», может содержать десятки скрытых UB, которые проявятся только при смене платформы — и найти их без специальных инструментов практически невозможно.
👉 Видео
Библиотека C/C++ разработчика
#буст
👍4❤3
Надо вынести кусок логики в функцию? Тогда можно воспользоваться встроенными возможностями редактора кода которым пользуешься.
• выдели код → Ctrl+Alt+M (Extract Function)
• выдели код → Ctrl+Shift+R → Extract to function
• выдели код → Ctrl+R, M (Extract Function)
void mainLogic(const std::string& user) {
// До рефакторинга
if (user.size() > 3 && user[0] == 'A') {
std::cout << "Valid user: " << user << std::endl;
}
}
После рефакторинга VS Code сам создаст функцию:
bool shouldProcessUser(const std::string& user) {
return user.size() > 3 && user[0] == 'A';
}
void mainLogic(const std::string& user) {
if (shouldProcessUser(user)) {
std::cout << "Valid user: " << user << std::endl;
}
}
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥1
Forwarded from Proglib.academy | IT-курсы
Правильно организованный корпоратив — это способ поднять мотивацию и улучшить атмосферу в компании.
Если продумать всё заранее, коллеги будут уходить не уставшими, а вдохновлёнными, с ощущением, что время проведено не зря.
В карточках пять конкретных действий и советов, которые помогут избежать хаоса и не огорчить коллег.
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3❤1🥱1
Если нужно запретить автоматический вывод типов для некоторых параметров шаблона, то
std::type_identity
поможет решить эту проблему.std::type_identity
из C++20 — простая обертка, которая предотвращает template argument deduction. Полезно для создания non-deduced contexts
.👉 Определение:
template<typename T>
struct type_identity { using type = T; };
template<typename T>
using type_identity_t = typename type_identity<T>::type;
💡 Примеры использования:
// БЕЗ type_identity - тип T выводится автоматически
template<typename T>
void convert_and_print(T from, T to) { /* ... */ }
convert_and_print(1, 2.5); // Ошибка: T не может быть int и double
// С type_identity - принуждаем указать тип явно
template<typename T>
void convert_and_print(T from, std::type_identity_t<T> to) {
std::cout << static_cast<T>(to) << std::endl;
}
convert_and_print<double>(1, 2.5); // OK: T = double}
💡 Функции сравнения:
template<typename T>
bool equal(const T& a, std::type_identity_t<const T&> b) {
return a == b;
}
std::string str = "hello";
equal(str, "hello"); // OK: T = std::string, второй параметр - const char*
🔍 Factory с явным указанием типа:
template<typename T>
std::unique_ptr<T> make_initialized(std::type_identity_t<T> init_value) {
return std::make_unique<T>(init_value);
}
// Тип нужно указать явно
auto ptr = make_initialized<std::string>("Hello World");
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍4
💡 Pointer Tagging в C++: искусство упаковки битов в указатель
Автор статьи рассказывает о технике pointer tagging — упаковке дополнительных данных прямо в указатели, используя неиспользуемые биты.
❗Ключевые моменты статьи:
• 64-битный указатель использует только 48 бит для адресации, оставляя 16 бит свободными
• malloc выравнивает память по 16-байтным границам, освобождая нижние 4 бита
• в итоге получается 20 свободных бит для хранения метаданных
Основной фокус — практическая реализация
Особенно актуально для разработчиков высокопроизводительных систем, работающих с динамическим полиморфизмом и древовидными структурами данных.
Вы узнаете, как Chrome V8 использует эту технику для различения целых чисел и ссылок на объекты, а ядро Linux — для хранения цвета узла в красно-чёрном дереве прямо в указателе на родителя.
➡️ Статья
Библиотека C/C++ разработчика
#буст
Автор статьи рассказывает о технике pointer tagging — упаковке дополнительных данных прямо в указатели, используя неиспользуемые биты.
❗Ключевые моменты статьи:
• 64-битный указатель использует только 48 бит для адресации, оставляя 16 бит свободными
• malloc выравнивает память по 16-байтным границам, освобождая нижние 4 бита
• в итоге получается 20 свободных бит для хранения метаданных
Основной фокус — практическая реализация
tagged_ptr
в C++ с автоматическим маскированием битов и поддержкой стандартных операторов указателей.Особенно актуально для разработчиков высокопроизводительных систем, работающих с динамическим полиморфизмом и древовидными структурами данных.
Вы узнаете, как Chrome V8 использует эту технику для различения целых чисел и ссылок на объекты, а ядро Linux — для хранения цвета узла в красно-чёрном дереве прямо в указателе на родителя.
➡️ Статья
Библиотека C/C++ разработчика
#буст
❤10🔥7👍1🥰1
🔍 Какой алгоритм поиска выбрать?
Выбор неправильного алгоритма поиска может в разы замедлить программу.
✏️ Выбираем по ситуации:
1️⃣ Неупорядоченные данные → std::find (O(n)):
2️⃣ Упорядоченные данные → std::binary_search (O(log n)):
3️⃣ Частые поиски → std::unordered_set (O(1) average):
4️⃣ Поиск с предикатом → std::find_if:
❌ Частая ошибка: Использование find на отсортированных данных.
Библиотека C/C++ разработчика
#буст
Выбор неправильного алгоритма поиска может в разы замедлить программу.
std::vector<int> nums = {3, 1, 4, 1, 5};
auto it = std::find(nums.begin(), nums.end(), 4);
if (it != nums.end()) {
std::cout << "Found at position " << std::distance(nums.begin(), it);
}
std::vector<int> sorted_nums = {1, 2, 3, 4, 5};
if (std::binary_search(sorted_nums.begin(), sorted_nums.end(), 3)) {
std::cout << "Found!";
}
std::unordered_set<int> lookup = {1, 3, 5, 7, 9};
if (lookup.find(5) != lookup.end()) {
std::cout << "Found instantly!";
}
auto even = std::find_if(nums.begin(), nums.end(),
[](int n) { return n % 2 == 0; });
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍1
Forwarded from Proglib.academy | IT-курсы
🔒 Оптимистическая vs пессимистическая блокировка: как выбрать и не пожалеть
Что произойдет, если несколько пользователей одновременно начнут менять одни и те же данные? Скорее всего — потеря изменений и ошибки.
Чтобы этого избежать, в системах используются блокировки: пессимистические — когда конфликтам не дают случиться, и оптимистические — когда система проверяет их только перед сохранением.
Разбираемся, как работают блокировки и какая из них лучше подойдет твоему приложению.
🔗 Читать статью
🏃♀️ Proglib Academy
#буст
Что произойдет, если несколько пользователей одновременно начнут менять одни и те же данные? Скорее всего — потеря изменений и ошибки.
Чтобы этого избежать, в системах используются блокировки: пессимистические — когда конфликтам не дают случиться, и оптимистические — когда система проверяет их только перед сохранением.
Разбираемся, как работают блокировки и какая из них лучше подойдет твоему приложению.
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5💯1
Если устали помнить порядок полей в структурах и случайно их путать, то
designated initializers
могут решить эту проблему.Designated initializers
позволяют инициализировать структуры по именам полей, делая код более читаемым и безопасным.struct Point {
int x, y, z;
};
Point p{.x = 10, .y = 20, .z = 30};
struct Config {
std::string host = "localhost";
int port = 8080;
bool ssl_enabled = false;
int timeout_ms = 5000;
};
// Указываем только нужные поля
Config cfg{
.host = "example.com",
.ssl_enabled = true
}; // port и timeout_ms получат значения по умолчанию
struct Database {
std::string connection_string;
int max_connections = 10;
};
struct AppConfig {
Database db;
std::string log_level = "INFO";
};
AppConfig config{
.db = {.connection_string = "postgresql://...", .max_connections = 20},
.log_level = "DEBUG"
};
struct DrawOptions {
bool fill = false;
int line_width = 1;
std::string color = "black";
float opacity = 1.0f;
};
void draw_rectangle(int x, int y, int w, int h, DrawOptions opts = {}) {
// implementation
}
// Явно указываем только нужные опции
draw_rectangle(10, 20, 100, 50, {
.fill = true,
.color = "red",
.opacity = 0.8f
});
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤4
std::variant (C++17)
— это union, который знает свой текущий тип и гарантирует безопасность.// C-style union — опасно!
union Data {
int i;
double d;
char* str;
};
Data data;
data.i = 42;
std::cout << data.d; // ❌ Читаем не то, что записали
std::variant<int, double, std::string> data;
data = 42; // Хранит int
data = 3.14; // Теперь хранит double
data = "hello"; // Теперь хранит string
// Безопасное получение значения
if (auto* val = std::get_if<int>(&data)) {
std::cout << "int: " << *val << '\n';
}
std::variant<int, std::string, double> v;
// Установка значения
v = 100;
v = "text";
v.emplace<std::string>("constructed in place");
// Проверка текущего типа
std::cout << v.index(); // Индекс типа: 0, 1, или 2
if (std::holds_alternative<int>(v)) {
std::cout << "Содержит int\n";
}
// Получение значения
try {
auto val = std::get<int>(v); // Бросит std::bad_variant_access
} catch (const std::bad_variant_access&) {
std::cerr << "Неверный тип!\n";
}
auto* ptr = std::get_if<std::string>(&v); // nullptr если не string
std::variant<int, double, std::string> v = 42;
// Обработка всех возможных типов
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << arg << '\n';
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << arg << '\n';
} else {
std::cout << "string: " << arg << '\n';
}
}, v);
cpptemplate<class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
// Элегантная обработка!
std::visit(overloaded{
[](int i) { std::cout << "int: " << i << '\n'; },
[](double d) { std::cout << "double: " << d << '\n'; },
[](const std::string& s) { std::cout << "string: " << s << '\n'; }
}, v);
template<typename T>
using Result = std::variant<T, std::string>; // Value или Error
Result<int> divide(int a, int b) {
if (b == 0) return "Division by zero";
return a / b;
}
auto result = divide(10, 0);
std::visit(overloaded{
[](int value) { std::cout << "Result: " << value << '\n'; },
[](const std::string& err) { std::cerr << "Error: " << err << '\n'; }
}, result);
std::variant
никогда не пустой (кроме исключительных ситуаций). Первый тип должен быть конструируемым по умолчанию.Используйте
std::variant
когда набор типов известен. std::any
— для действительно произвольных типов.Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥4❤2
🔍 Промпт: Регулярные выражения в C++
Работаете с регулярками в C++ и запутались в std::regex? Есть простой лайфхак!
✏️ Используйте промпт
❗️ Пример использования
Запрос:
Получаем:
🔥 Что можно запрашивать
✅ Валидация email, телефонов, URL
✅ Извлечение данных из строк
✅ Поиск паттернов в логах
✅ Парсинг форматов файлов
✅ Проверка форматов дат/времени
Библиотека C/C++ разработчика
#буст
Работаете с регулярками в C++ и запутались в std::regex? Есть простой лайфхак!
Write a regular expression that matches / Write a RegEx pattern for:
[ваше описание]
Запрос:
Email addresses with validation
Получаем:
std::regex email_pattern(
R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
);
Библиотека C/C++ разработчика
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2