🔧 Как правильно передать данные в std::thread
Передача параметров в потоки — источник багов даже у опытных разработчиков. Главная проблема: время жизни объектов и способы передачи.
Пошаговое решение:
1️⃣ Используйте std::ref для ссылок
2️⃣ Копируйте простые типы по значению
3️⃣ Перемещайте тяжелые объекты через std::move
4️⃣ Избегайте сырых указателей
⚠️ Частые ошибки:
• Передача ссылок без std::ref
• Доступ к локальным переменным после их уничтожения
💡 При сомнениях используйте передачу по значению🤓
Библиотека C/C++ разработчика #буст
Передача параметров в потоки — источник багов даже у опытных разработчиков. Главная проблема: время жизни объектов и способы передачи.
Пошаговое решение:
1️⃣ Используйте std::ref для ссылок
2️⃣ Копируйте простые типы по значению
3️⃣ Перемещайте тяжелые объекты через std::move
4️⃣ Избегайте сырых указателей
#include <thread>
#include <string>
void process_data(int value, const std::string& text, std::vector<int>& result) {
// Обработка данных
result.push_back(value);
}
int main() {
int number = 42;
std::string message = "Hello";
std::vector<int> results;
// Правильная передача параметров
std::thread t(process_data, number,
std::cref(message), // const ссылка
std::ref(results)); // обычная ссылка
t.join();
return 0;
}
⚠️ Частые ошибки:
• Передача ссылок без std::ref
• Доступ к локальным переменным после их уничтожения
💡 При сомнениях используйте передачу по значению🤓
Библиотека C/C++ разработчика #буст
🥰4❤1🥱1
В шаблонах
C++
ошибки типов приводят к критическим сообщениям компилятора на десятки строк. Отладка становится кошмаром, особенно для новичков в команде.
C++ Concepts
позволяют явно указать требования к типам шаблонов. Это делает код самодокументируемым и дает понятные сообщения об ошибках.#include <concepts>
// Определяем концепт для числовых типов
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
// Функция принимает только числовые типы
template<Numeric T>
T multiply(T a, T b) {
return a * b;
}
int main() {
auto result1 = multiply(5, 10); // OK: int
auto result2 = multiply(3.14, 2.0); // OK: double
// auto result3 = multiply("hello", "world"); // Ошибка компиляции с понятным сообщением
return 0;
}
• Понятные сообщения об ошибках компиляции
• Самодокументируемый код с явными требованиями к типам
• Улучшенная производительность компиляции за счет раннего отсева неподходящих типов
• Возможность перегрузки функций на основе концептов
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🥰5❤1
📦 Создание модулей C++20 для быстрой компиляции
❗️ Проблема:
Медленная компиляция из-за #include файлов.
✅ Решение:
1️⃣ Создайте
2️⃣ Экспортируйте нужные декларации
3️⃣ Импортируйте модуль в коде
❌ Частые ошибки:
Забывать ключевое слово export для публичных функций.
💡 Совет:
Modules работают не во всех компиляторах — проверяйте поддержку!
Библиотека C/C++ разработчика #буст
Modules
— это будущее организации C++ кода.Медленная компиляция из-за #include файлов.
module interface
файл// math_utils.ixx
export module math_utils;
export namespace math {
int add(int a, int b) {
return a + b;
}
double sqrt_approx(double x) {
return x / 2.0; // Упрощенная версия
}
}
// main.cpp
import math_utils;
#include <iostream>
int main() {
std::cout << math::add(3, 4) << std::endl;
return 0;
}
Забывать ключевое слово export для публичных функций.
Modules работают не во всех компиляторах — проверяйте поддержку!
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤1
🔄 std::source_location: автоматическое логирование
Забудьте FILE и LINE! std::source_location автоматически получает информацию о местоположении в коде.
Важно:
Библиотека C/C++ разработчика #буст
Забудьте FILE и LINE! std::source_location автоматически получает информацию о местоположении в коде.
#include <iostream>
#include <source_location>
#include <string_view>
void log_error(std::string_view message,
const std::source_location& loc = std::source_location::current()) {
std::cout << "ОШИБКА в " << loc.file_name()
<< ":" << loc.line()
<< " в функции " << loc.function_name()
<< " - " << message << std::endl;
}
void problematic_function() {
log_error("Что-то пошло не так!"); // Автоматически получит location
}
int main() {
log_error("Ошибка инициализации");
problematic_function();
return 0;
}
Важно:
source_location
вычисляется в точке вызова, не в точке определения функции.Библиотека C/C++ разработчика #буст
🔥20❤1👏1
Периодически требуется реализовать интеграцию с STL алгоритмами. Для этого необходимо реализовать правильные API.
Проблема: Нужно создать контейнер, работающий с range-based for и STL.
#include <iterator>
#include <algorithm>
#include <iostream>
template<typename T>
class CircularBuffer {
T* data;
size_t capacity_;
size_t size_;
size_t head_ = 0;
public:
explicit CircularBuffer(size_t capacity)
: data(new T[capacity]), capacity_(capacity), size_(0) {}
~CircularBuffer() { delete[] data; }
// Iterator class
class iterator {
T* ptr;
size_t capacity;
size_t index;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
iterator(T* ptr, size_t capacity, size_t index)
: ptr(ptr), capacity(capacity), index(index) {}
reference operator*() { return ptr[index % capacity]; }
pointer operator->() { return &ptr[index % capacity]; }
iterator& operator++() {
++index;
return *this;
}
iterator operator++(int) {
iterator tmp = *this;
++index;
return tmp;
}
bool operator==(const iterator& other) const {
return index == other.index;
}
bool operator!=(const iterator& other) const {
return !(*this == other);
}
};
void push(const T& item) {
data[(head_ + size_) % capacity_] = item;
if (size_ < capacity_) {
++size_;
} else {
++head_;
head_ %= capacity_;
}
}
iterator begin() { return iterator(data, capacity_, head_); }
iterator end() { return iterator(data, capacity_, head_ + size_); }
size_t size() const { return size_; }
bool empty() const { return size_ == 0; }
};
int main() {
CircularBuffer<int> buffer(5);
// Заполняем буфер
for (int i = 1; i <= 7; ++i) {
buffer.push(i);
}
// Range-based for работает!
for (const auto& item : buffer) {
std::cout << item << " ";
}
std::cout << std::endl;
// STL алгоритмы работают!
auto it = std::find(buffer.begin(), buffer.end(), 5);
if (it != buffer.end()) {
std::cout << "Found: " << *it << std::endl;
}
}
Частые ошибки: Не реализовать все необходимые operator для итератора.
💡 Совет: Правильные итераторы делают ваш контейнер first-class citizen в ST.
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3
⚙️ Boost.Program_options
Boost.Program_options — это библиотека для элегантного парсинга аргументов командной строки и конфигурационных файлов с автоматической генерацией help и валидацией параметров.
👉 Установка:
💡 Примеры использования:
✍️ Дополнительные возможности:
— Поддержка конфигурационных файлов
— Валидация типов и значений
— Группировка опций
— Автоматическая генерация справки
🔍 Специальная фича:
Библиотека C/C++ разработчика #буст
Устали писать парсинг argc/argv вручную для каждого приложения?
Boost.Program_options — это библиотека для элегантного парсинга аргументов командной строки и конфигурационных файлов с автоматической генерацией help и валидацией параметров.
👉 Установка:
# Часть Boost libraries
sudo apt install libboost-program-options-dev
# Или через vcpkg: vcpkg install boost-program-options
💡 Примеры использования:
#include <boost/program_options.hpp>
namespace po = boost::program_options;
po::options_description desc("Options");
desc.add_options()
("help,h", "Help message")
("input,i", po::value<string>(), "Input file")
("verbose,v", "Verbose output");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
✍️ Дополнительные возможности:
— Поддержка конфигурационных файлов
— Валидация типов и значений
— Группировка опций
— Автоматическая генерация справки
🔍 Специальная фича:
// Комбинирование источников конфигурации
po::store(po::parse_command_line(argc, argv, desc), vm);
po::store(po::parse_config_file("config.ini", desc), vm);
po::notify(vm); // Применение всех значений
Библиотека C/C++ разработчика #буст
🔥5❤3👍3❤🔥1
🚀 std::unreachable в C++23
Компилятор не всегда понимает, что некоторые участки кода недостижимы. std::unreachable() помогает ему генерировать более оптимальный код.
📋 Пошаговое решение:
1️⃣ Подключите заголовок
2️⃣ Используйте в switch без default
3️⃣ Применяйте в условных блоках
⚠️ Частые ошибки:
❌ Неправильно: Использовать когда код действительно достижим
❌ Неправильно: Забывать про обработку ошибок перед unreachable()
✅ Правильно: Использовать только когда логически уверены в недостижимости
🎯 Практический совет:
std::unreachable() - это контракт с компилятором. Если код всё-таки достигнет этой точки, поведение неопределено. Используйте только когда на 100% уверены.
🎯 Альтернатива:
В старых стандартах используйте
🐸 Библиотека C/C++ разработчика #буст
Компилятор не всегда понимает, что некоторые участки кода недостижимы. std::unreachable() помогает ему генерировать более оптимальный код.
📋 Пошаговое решение:
1️⃣ Подключите заголовок
#include <utility> // C++23
2️⃣ Используйте в switch без default
enum class Color { RED, GREEN, BLUE };
std::string colorToString(Color c) {
switch(c) {
case Color::RED: return "red";
case Color::GREEN: return "green";
case Color::BLUE: return "blue";
}
std::unreachable(); // Говорим компилятору: сюда не попадём!
}
3️⃣ Применяйте в условных блоках
int divide(int a, int b) {
if (b != 0) {
return a / b;
}
// Логически сюда не должны попасть
handleError(); // Наша обработка
std::unreachable(); // Оптимизация для компилятора
}
⚠️ Частые ошибки:
❌ Неправильно: Использовать когда код действительно достижим
❌ Неправильно: Забывать про обработку ошибок перед unreachable()
✅ Правильно: Использовать только когда логически уверены в недостижимости
🎯 Практический совет:
std::unreachable() - это контракт с компилятором. Если код всё-таки достигнет этой точки, поведение неопределено. Используйте только когда на 100% уверены.
🎯 Альтернатива:
В старых стандартах используйте
__builtin_unreachable()
(GCC/Clang) или __assume(false)
(MSVC).Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤4
✏️ Промпт дня: Создание юнит-тестов для надёжного кода
Юнит-тесты — это автоматизированные тесты, которые проверяют поведение отдельных частей кода в изоляции. Они помогают обнаруживать ошибки на ранней стадии и значительно упрощают поддержку кода в C++.
☀️ Решение с помощью AI
🧋 Пример трансформации
До:
После:
✏️ Как часто вы пишете юнит-тесты для своего C++ кода?
🐸 Библиотека C/C++ разработчика #буст
Юнит-тесты — это автоматизированные тесты, которые проверяют поведение отдельных частей кода в изоляции. Они помогают обнаруживать ошибки на ранней стадии и значительно упрощают поддержку кода в C++.
☀️ Решение с помощью AI
Please write unit tests for [имя файла и модуля] to ensure its proper functioning
[ВСТАВЬТЕ ВАШ КОД ЗДЕСЬ]
🧋 Пример трансформации
До:
class Calculator {
public:
int add(int a, int b) { return a + b; }
int divide(int a, int b) {
if (b == 0) throw std::invalid_argument("Division by zero");
return a / b;
}
};
После:
#include <gtest/gtest.h>
TEST(CalculatorTest, AddPositiveNumbers) {
Calculator calc;
EXPECT_EQ(calc.add(2, 3), 5);
}
TEST(CalculatorTest, DivideByZero) {
Calculator calc;
EXPECT_THROW(calc.divide(10, 0), std::invalid_argument);
}
TEST(CalculatorTest, DivideNormalCase) {
Calculator calc;
EXPECT_EQ(calc.divide(10, 2), 5);
}
✏️ Как часто вы пишете юнит-тесты для своего C++ кода?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥7❤1👍1
Хотите безопасную сериализацию? Создайте концепт для проверки того, что тип можно сериализовать и десериализовать.
#include <concepts>
#include <iostream>
#include <string>
#include <sstream>
// Концепт для сериализуемых типов
template<typename T>
concept Serializable = requires(T obj, std::ostream& os, std::istream& is) {
{ obj.serialize(os) } -> std::same_as<void>;
{ T::deserialize(is) } -> std::same_as<T>;
};
// Пример сериализуемого класса
struct Person {
std::string name;
int age;
void serialize(std::ostream& os) const {
os << name << " " << age;
}
static Person deserialize(std::istream& is) {
Person p;
is >> p.name >> p.age;
return p;
}
};
// Функция для работы с сериализуемыми объектами
template<Serializable T>
void save_and_load(const T& obj) {
std::stringstream ss;
// Сериализация
obj.serialize(ss);
std::cout << "Serialized: " << ss.str() << std::endl;
// Десериализация
T loaded = T::deserialize(ss);
std::cout << "Deserialized successfully" << std::endl;
}
// Использование
void example() {
Person p{"Alice", 25};
save_and_load(p); // ✅ Работает
// save_and_load(42); // ❌ Ошибка компиляции
}
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3
⏰ std::chrono — работа со временем
👉 Подключение:
💡 Примеры использования:
Основные типы:
— duration для промежутков времени
— time_point для моментов времени
— clock для источников времени
Часы (clocks):
— system_clock системное время
— steady_clock монотонное время
— high_resolution_clock наивысшая точность
Единицы времени:
— nanoseconds, microseconds, milliseconds
— seconds, minutes, hours
— Пользовательские единицы
Библиотека C/C++ разработчика #буст
Используете time_t и clock() для измерения времени?
std::chrono
в C++11 предоставляет типобезопасную работу со временем. Высокая точность, читаемый код и портабельность.👉 Подключение:
#include <chrono>
using namespace std::chrono;
💡 Примеры использования:
auto start = high_resolution_clock::now();
expensive_operation();
auto end = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(end - start);
std::cout << "Operation took: " << duration.count() << "ms" << std::endl;
std::this_thread::sleep_for(seconds(2)); // Спать 2 секунды
std::this_thread::sleep_for(milliseconds(500)); // Спать 500 мс
std::this_thread::sleep_for(2s); // C++14 literals
Основные типы:
— duration для промежутков времени
— time_point для моментов времени
— clock для источников времени
Часы (clocks):
— system_clock системное время
— steady_clock монотонное время
— high_resolution_clock наивысшая точность
Единицы времени:
— nanoseconds, microseconds, milliseconds
— seconds, minutes, hours
— Пользовательские единицы
Библиотека C/C++ разработчика #буст
🔥11
✏️ Промпт дня: Улучшение обработки ошибок
Обработка ошибок — один из самых критичных аспектов разработки на C++. Неправильная обработка исключений может привести к утечкам памяти, неопределенному поведению и краху приложения.
☀️ Решение с помощью AI
Для улучшения системы обработки ошибок в вашем коде используйте следующий промпт:
🧋 Пример трансформации
До:
После (с улучшенной обработкой ошибок):
✏️ Как часто в вашем коде встречаются необработанные ошибки? Пишите в комментариях.
Библиотека C/C++ разработчика #буст
Обработка ошибок — один из самых критичных аспектов разработки на C++. Неправильная обработка исключений может привести к утечкам памяти, неопределенному поведению и краху приложения.
☀️ Решение с помощью AI
Для улучшения системы обработки ошибок в вашем коде используйте следующий промпт:
How can I improve the error handling in my C++ code? [ВАШ КОД]
🧋 Пример трансформации
До:
int divide(int a, int b) {
return a / b; // Деление на ноль = краш
}
std::vector<int> readFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<int> data;
int value;
while (file >> value) {
data.push_back(value);
}
return data; // Что если файл не открылся?
}
После (с улучшенной обработкой ошибок):
#include <stdexcept>
#include <optional>
std::optional<int> divide(int a, int b) {
if (b == 0) {
return std::nullopt;
}
return a / b;
}
std::vector<int> readFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error("Cannot open file: " + filename);
}
std::vector<int> data;
int value;
while (file >> value) {
data.push_back(value);
}
if (file.bad()) {
throw std::runtime_error("Error reading file: " + filename);
}
return data;
}
✏️ Как часто в вашем коде встречаются необработанные ошибки? Пишите в комментариях.
Библиотека C/C++ разработчика #буст
👍3❤1🤔1
std::vector<std::vector<int> >
с пробелом? Давайте посмотрим, как изменилась работа с типами за 25 лет!//Verbosity nightmare
std::vector<std::pair<std::string, int> > vec; // пробел обязателен!
for (std::vector<std::pair<std::string, int> >::iterator it = vec.begin();
it != vec.end(); ++it) {
// работаем с *it
}
// auto и range-based for
std::vector<std::pair<std::string, int>> vec; // >> теперь OK!
for (auto& item : vec) {
// намного чище!
}
// Не нужно указывать типы
std::vector vec{std::pair{"hello", 42}, {"world", 24}}; // CTAD!
std::optional opt = some_function(); // тип выводится автоматически
// Structured bindings
for (auto [name, value] : vec) {
std::cout << name << ": " << value << "\n";
}
#include <concepts>
template<std::integral T> // Концепты!
auto process(T value) {
return value * 2;
}
// Abbreviated function templates
auto add(std::integral auto a, std::integral auto b) {
return a + b;
}
// if consteval для compile-time проверок
constexpr auto get_value() {
if consteval {
return 42; // compile-time версия
} else {
return expensive_runtime_calc(); // runtime версия
}
}
// Multidimensional subscript operator
matrix[1, 2, 3] = value; // вместо matrix[1][2][3]
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤2
😈 Modules в C++20 - будущее или очередной провал?
5 лет назад: "Modules решат все проблемы! Быстрая компиляция! Настоящая инкапсуляция!"
2025 год: Поддержка модулей все еще экспериментальная, build системы путаются, а простой hello world на модулях собирается в 3 раза дольше классического 😅
🐊 Реальность модулей:
- CMake = beta поддержка
- Legacy код = не портируется
- Compile times = пока что хуже
😡 Парадокс:
Хотели ускорить компиляцию, получили новые проблемы с build системами.
Но справедливости ради - концепция правильная. Проблема в том, что экосистема не готова. Может через 5 лет будет по-другому?
💡 Сравнение:
❓ Вопрос:
Стоит ли уже сейчас изучать modules или подождать еще пару лет?
🔥 Уже использую в пет проектах
⚡️ Изучаю, но не применяю
👾 Жду стабилизации
❤️ Пока что #include рулит
Библиотека C/C++ разработчика #междусабойчик
Modules обещали революцию, а получили головную боль!
5 лет назад: "Modules решат все проблемы! Быстрая компиляция! Настоящая инкапсуляция!"
2025 год: Поддержка модулей все еще экспериментальная, build системы путаются, а простой hello world на модулях собирается в 3 раза дольше классического 😅
- CMake = beta поддержка
- Legacy код = не портируется
- Compile times = пока что хуже
Хотели ускорить компиляцию, получили новые проблемы с build системами.
Но справедливости ради - концепция правильная. Проблема в том, что экосистема не готова. Может через 5 лет будет по-другому?
// Классика: работает везде
#include <iostream>
#include "my_header.h"
// Modules: работает... иногда... если повезет
import std.io;
import my.module;
Стоит ли уже сейчас изучать modules или подождать еще пару лет?
🔥 Уже использую в пет проектах
⚡️ Изучаю, но не применяю
👾 Жду стабилизации
Библиотека C/C++ разработчика #междусабойчик
Please open Telegram to view this post
VIEW IN TELEGRAM
❤22👾18⚡5🔥3
🔹 Зачем?
Работа с перечислениями (enum) в C++ часто требует дополнительного кода: преобразование в строку, проверка значений, итерация по всем вариантам. Библиотека conjure_enum автоматизирует эту рутину!
🔹 Что умеет?
✅ Генерация to_string() для enum
✅ Проверка валидности значений (is_valid)
✅ Итерация по всем элементам enum
✅ Поддержка enum и enum class
✅ Минимальный оверхед (всё вычисляется на этапе компиляции)
🔹 Пример использования:
#include "conjure_enum.h"
CONJURE_DEFINE_ENUM(Color, Red, Green, Blue)
int main() {
Color c = Color::Green;
std::cout << conjure_enum::to_string(c); // "Green"
std::cout << conjure_enum::is_valid(42); // false
for (Color value : conjure_enum::values<Color>()) { ... }
}
🔹 Плюсы:
✔️ Заголовочный-only (просто подключи conjure_enum.h)
✔️ Не требует C++20 (работает даже на C++11)
✔️ Лёгкая интеграция в существующий код
💡 Кому пригодится?
— Тем, кто устал писать switch-case для enum-ов
— Если нужна удобная отладка (вывод значений в лог)
— Для валидации конфигов/сетевых данных
🔗 Ссылка
Библиотека C/C++ разработчика #буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤1