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

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

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

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

РКН: https://gosuslugi.ru/snet/67a5bac324c8ba6dcaa1ad17
Download Telegram
🌈 5 правил успешного корпоратива

Правильно организованный корпоратив — это способ поднять мотивацию и улучшить атмосферу в компании.

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

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

➡️ Читать статью

🏃‍♀️ Proglib Academy

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁31🥱1
🌻 std::type_identity — предотвращение template argument deduction

Если нужно запретить автоматический вывод типов для некоторых параметров шаблона, то 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 свободных бит для хранения метаданных

Основной фокус — практическая реализация tagged_ptr в C++ с автоматическим маскированием битов и поддержкой стандартных операторов указателей.

Особенно актуально для разработчиков высокопроизводительных систем, работающих с динамическим полиморфизмом и древовидными структурами данных.

Вы узнаете, как Chrome V8 использует эту технику для различения целых чисел и ссылок на объекты, а ядро Linux — для хранения цвета узла в красно-чёрном дереве прямо в указателе на родителя.

➡️ Статья

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

#буст
10🔥7👍1🥰1
🔍 Какой алгоритм поиска выбрать?

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


✏️ Выбираем по ситуации:

1️⃣ Неупорядоченные данные → std::find (O(n)):

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);
}



2️⃣ Упорядоченные данные → std::binary_search (O(log n)):

std::vector<int> sorted_nums = {1, 2, 3, 4, 5};
if (std::binary_search(sorted_nums.begin(), sorted_nums.end(), 3)) {
std::cout << "Found!";
}



3️⃣ Частые поиски → std::unordered_set (O(1) average):

std::unordered_set<int> lookup = {1, 3, 5, 7, 9};
if (lookup.find(5) != lookup.end()) {
std::cout << "Found instantly!";
}



4️⃣ Поиск с предикатом → std::find_if:

auto even = std::find_if(nums.begin(), nums.end(), 
[](int n) { return n % 2 == 0; });



Частая ошибка: Использование find на отсортированных данных.


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍1
🔒 Оптимистическая vs пессимистическая блокировка: как выбрать и не пожалеть

Что произойдет, если несколько пользователей одновременно начнут менять одни и те же данные? Скорее всего — потеря изменений и ошибки.

Чтобы этого избежать, в системах используются блокировки: пессимистические — когда конфликтам не дают случиться, и оптимистические — когда система проверяет их только перед сохранением.

Разбираемся, как работают блокировки и какая из них лучше подойдет твоему приложению.

🔗 Читать статью

🏃‍♀️ Proglib Academy

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5💯1
⚡️ Designated Initializers — именованная инициализация из C++20

Если устали помнить порядок полей в структурах и случайно их путать, то 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
👍104
👁 std::variant — типобезопасный union

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::visit — главная фишка:

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);



🍪 Перегруженный visitor (C++17 трюк):

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::any:

Используйте std::variant когда набор типов известен. std::any — для действительно произвольных типов.


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥42
🔍 Промпт: Регулярные выражения в 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,})"
);



🔥 Что можно запрашивать

Валидация email, телефонов, URL
Извлечение данных из строк
Поиск паттернов в логах
Парсинг форматов файлов
Проверка форматов дат/времени


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2
🔥 6 горячих клавиш VS Code

Горячие клавиши — добро, польза и экономия времени. Давайте разберёмся, как с их помощью упростить себе жизнь в Visual Studio Code.

1️⃣ Перейти к парной скобке

Windows — Ctrl + Shift + \

macOS — Shift + Command + \

Когда кода становится много, очень просто запутаться в закрывающих и открывающих скобках, непонятно, где какой блок, и вообще, что происходит. На помощь приходит Ctrl + Shift + \ — это хорошее дополнение к стандартной подсветке парных скобок в VS Code.

2️⃣ Переименовать переменную

Windows — F2

macOS — F2

Писали, писали, а старший разработчик пришёл и сказал, что ваши переменные a, b и c — дурной тон. Чтобы не выискивать их по всему документу и не менять руками, есть F2.

3️⃣ Отформатировать документ

Windows — Shift + Alt + F

macOS — Shift + Option + F

VS Code предложит установить расширение или выбрать из существующих, а потом красиво отформатирует документ — расставит по местам блоки и скобки, сделает строки кода читаемыми.

4️⃣ Перейти к переменной

Windows — F12

macOS — F12

Иногда вообще непонятно, откуда взялась переменная, какая у неё область видимости и где она объявлена. F12 перенесёт вас к объявлению выделенной переменной, функции или метода. Если объявление в другом файле — всё равно перенесёт.

5️⃣ Включить или выключить перенос слов

Windows — Alt + Z

macOS — Option + Z

Если строки кода или текст не вмещаются в редактор по ширине, включите перенос.

6️⃣ Включить дзен-режим

Windows — Ctrl + KZ

macOS — Command + KZ

Лучшее решение для тех, кто входит в состояние потока, когда пишет код. Дзен-режим скрывает все панели, разворачивает редактор на весь экран, и вы можете плыть в волнах кода и думать только о нём. Чтобы вернуться в реальный мир, нажмите Escape.

🐸 Библиотека мобильного разработчика

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🥰1
⚙️ Почему классический ООП тормозит игровые движки — и что с этим делать

Обработка тысяч объектов в реальном времени превращается в кошмар с традиционным C++. Программист из Блэкхаб Геймс показывает, как Entity Component System решает проблемы производительности.


🧨 Что узнаешь из доклада:

• Почему наследование и виртуальные таблицы убивают производительность при обработке тысяч сущностей
• Как ECS разделяет данные и логику
• Data-Oriented Design: как пулы компонентов улучшают кэш-локальность и позволяют использовать SIMD
• Простая многопоточность без головной боли
• Практическая реализация на библиотеке Flex с примерами кода
• Почему доступ через ID лучше указателей в динамичных игровых сценах

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

👉 Видео

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

#буст
4👍1👏1
Перевод: Cуществует ли испанский язык программирования? Si++ (Да по испански)

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

#буст
😁21🥱3💯1
🔥 std::list - когда он действительно нужен

Проблема: Многие выбирают std::list думая, что вставка O(1) всегда лучше, но забывают про cache locality.


✏️ Когда list ДЕЙСТВИТЕЛЬНО лучше:


1️⃣ Частые вставки/удаления в середине + большие объекты:
struct HeavyObject { 
std::array<double, 1000> data;
};

std::list<HeavyObject> items; // Не перемещаем данные
auto it = items.begin();
std::advance(it, 5);
items.insert(it, HeavyObject{}); // Быстро!



2️⃣ Когда нужна стабильность итераторов:
std::list<int> data = {1, 2, 3};
auto it = data.begin();
data.push_back(4); // it все ещё валиден!



3️⃣ В 90% случаев vector быстрее list:
// vector выигрывает благодаря cache:
std::vector<int> fast; // Данные подряд в памяти
std::list<int> slow; // Прыжки по указателям


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🙏10👍82👾1
🎲 std::random vs rand() — генерация случайных чисел

Старый rand() из Си имеет множество проблем: плохое качество, ограниченный диапазон, глобальное состояние. В C++11 появились современные генераторы из <random>.

Старый подход:
#include <cstdlib>
#include <ctime>

srand(time(nullptr)); // Предсказуемо!
int dice = rand() % 6 + 1; // Неравномерное распределение!
double prob = rand() / (double)RAND_MAX; // Плохая точность


🍒 Современный подход:
#include <random>

// Инициализация генератора (один раз)
std::random_device rd;
std::mt19937 gen(rd()); // Mersenne Twister

// Равномерное распределение [1, 6]
std::uniform_int_distribution dice(1, 6);
int roll = dice(gen);

// Вещественное [0.0, 1.0)
std::uniform_real_distribution prob(0.0, 1.0);
double p = prob(gen);

// Нормальное распределение
std::normal_distribution normal(0.0, 1.0);
double value = normal(gen);



✏️ Доступные распределения:

• uniform_int_distribution — целые числа
• uniform_real_distribution — вещественные
• normal_distribution — гауссово
• bernoulli_distribution — булево
• exponential_distribution, poisson_distribution и другие

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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥7🌚2👾1
🦀 Транспиляция кода: от одного языка к другому

Представьте ситуацию: вы нашли идеальное решение на GitHub, но оно написано не на том языке. Или ваш руководитель прочитал статью о новом фреймворке, и теперь нужно переписывать всю кодовую базу. Знакомо?

Хорошая новость: современные LLM-модели отлично справляются с транспиляцией кода между языками программирования.


✏️ Промпт

Rewrite the following code in C++:

[Вставь свой код сюда]



🍴 Пример использования

# Исходный Python код

def count_words(text):
"""Count word frequency in text"""
words = text.lower().split()
freq = {}
for word in words:
freq[word] = freq.get(word, 0) + 1
return freq

# Пример использования
text = "hello world hello python world"
print(count_words(text))
# Output: {'hello': 2, 'world': 2, 'python': 1}


Результат:

#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <algorithm>

std::map<std::string, int> count_words(const std::string& text) {
std::map<std::string, int> freq;
std::istringstream stream(text);
std::string word;

while (stream >> word) {
// Convert to lowercase
std::transform(word.begin(), word.end(), word.begin(), ::tolower);
freq[word]++;
}

return freq;
}

int main() {
std::string text = "hello world hello python world";
auto result = count_words(text);

for (const auto& [word, count] : result) {
std::cout << word << ": " << count << std::endl;
}

return 0;
}


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


#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👾1
⚡️ VS Code: мультикурсоры

Знакомо ли тебе чувство, когда нужно изменить одинаковые переменные в 15 местах, и ты тыкаешь мышкой чтобы поменять каждое из них?


Решение: Ctrl+D - выделяет каждое следующее вхождения

Выдели слово → жми Ctrl+D для каждого следующего → редактируй все сразу

// Было
int temp = 0;
temp = getValue();
process(temp);
return temp;

// Жмёшь Ctrl+D три раза на temp и меняешь
int result = 0;
result = getValue();
process(result);
return result;


💣
Бонус: Ctrl+Shift+L выделяет ВСЕ вхождения сразу. Но осторожно - может зацепить лишнее.


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


#буст
👍83
🪣 50 фраз которые портят ваше резюме

Рекрутеры видят одно и то же в каждом втором резюме: «командный игрок», «работаю с современными технологиями», «обладаю аналитическим складом ума». Эти клише не просто скучны — они ставят под сомнение вашу компетентность. Разбираем 50+ шаблонных фраз по всем IT-направлениям и показываем, как их заменить или вообще выкинуть.

Читаем дальше...

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

#буст
😁2
🍬 Потоки могут общаться через condition_variable

Чтобы один поток ожидал другого можно воспользоваться condition_variable.


🍴 Пошаговое решение:

1️⃣ Создайте condition_variable и mutex
2️⃣ Поток ждёт через wait()
3️⃣ Другой поток сигналит через notify_one/notify_all

#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; }); // Ждём сигнала

std::cout << "Worker started!\n";
}

int main() {
std::thread t(worker);

std::this_thread::sleep_for(std::chrono::seconds(1));

{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one(); // Будим поток

t.join();
return 0;
}


❗️ Частая ошибка: Забыть проверять условие в wait()

💡 Совет: Всегда передавайте предикат в wait()


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1🙏1
🔥 Фича: std::scoped_lock (C++17)

Захват нескольких мьютексов вручную рискует deadlock при неправильном порядке.

std::scoped_lock атомарно захватывает несколько мьютексов, избегая взаимоблокировок.

До:

std::lock_guard lock1(mtx1);
std::lock_guard lock2(mtx2); // deadlock риск!


После:

std::scoped_lock lock(mtx1, mtx2); // безопасно



💡 Используете std::scoped_lock в своём коде?

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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥61
💡 C++: Генерация шаблонного кода

Запуск нового C++ проекта часто начинается с рутины: создание классов с конструкторами, деструкторами, операторами копирования/перемещения, шаблоны паттернов... Звучит очень знакомо и ужасно скучно. Что хотябы немного облегчить себе задачу можно воспользоваться AI.

Хотя AI и не знает бизнес-логику проекта, но зато он отлично справляется с созданием базовой структуры проекта.


✏️ Пример использования


Промпт:

Создай boilerplate код для C++ класса ResourceManager, 
который управляет игровыми ресурсами (текстуры, звуки).
Класс должен быть синглтоном,
шаблонными методами загрузки/получения ресурсов и
thread-safe доступом.


Результат:


#pragma once
#include <memory>
#include <unordered_map>
#include <mutex>
#include <string>

template<typename T>
class ResourceManager {
private:
std::unordered_map<std::string, std::shared_ptr<T>> resources;
mutable std::mutex mutex;

// Приватный конструктор для синглтона
ResourceManager() = default;

public:
// Удаляем конструктор копирования и оператор присваивания
ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete;

// Конструктор и оператор перемещения
ResourceManager(ResourceManager&&) noexcept = default;
ResourceManager& operator=(ResourceManager&&) noexcept = default;

// Деструктор
~ResourceManager() = default;

// Получение единственного экземпляра (Meyer's Singleton)
static ResourceManager& getInstance() {
static ResourceManager instance;
return instance;
}

// Загрузка ресурса
template<typename... Args>
bool load(const std::string& id, Args&&... args) {
std::lock_guard<std::mutex> lock(mutex);

if (resources.find(id) != resources.end()) {
return false; // Уже загружен
}

auto resource = std::make_shared<T>(std::forward<Args>(args)...);
resources[id] = resource;
return true;
}

// Получение ресурса
std::shared_ptr<T> get(const std::string& id) const {
std::lock_guard<std::mutex> lock(mutex);

auto it = resources.find(id);
return (it != resources.end()) ? it->second : nullptr;
}

// Выгрузка ресурса
bool unload(const std::string& id) {
std::lock_guard<std::mutex> lock(mutex);
return resources.erase(id) > 0;
}

// Очистка всех ресурсов
void clear() {
std::lock_guard<std::mutex> lock(mutex);
resources.clear();
}
};


🍿 Что получили?

• Полностью рабочий шаблонный класс
• Thread-safe операции

Теперь можешь сразу добавлять свою бизнес-логику, вместо того чтобы тратить время на шаблонный код🙂

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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱3👍21