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

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

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

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

РКН: https://gosuslugi.ru/snet/67a5bac324c8ba6dcaa1ad17
Download Telegram
🍴 Callback chain (цепочка обработчиков)

Надоело писать if-else лесенки для обработки событий? Лямбды превращают это в изящную цепочку.


Паттерн Chain of Responsibility через лямбды позволяет регистрировать обработчики, которые выполняются последовательно, пока кто-то не обработает событие:

#include <vector>
#include <functional>
#include <algorithm>

template<typename Event>
class CallbackChain {
using Handler = std::function<bool(const Event&)>;
std::vector<Handler> handlers_;

public:
// Добавить обработчик в конец цепочки
void add_handler(Handler handler) {
handlers_.push_back(std::move(handler));
}

// Добавить обработчик в начало (высокий приоритет)
void add_handler_front(Handler handler) {
handlers_.insert(handlers_.begin(), std::move(handler));
}

// Обработать событие (возвращает true, если кто-то обработал)
bool handle(const Event& event) const {
for (const auto& handler : handlers_) {
if (handler(event)) {
return true; // Обработчик вернул true - останавливаемся
}
}
return false; // Никто не обработал
}

// Уведомить всех обработчиков (не останавливаясь)
void notify_all(const Event& event) const {
for (const auto& handler : handlers_) {
handler(event); // Игнорируем возвращаемое значение
}
}

// Очистить все обработчики
void clear() { handlers_.clear(); }

size_t size() const { return handlers_.size(); }
};


Использование для обработки HTTP-запросов:

struct HttpRequest {
std::string path;
std::string method;
std::map<std::string, std::string> params;
};

CallbackChain<HttpRequest> router;

// Регистрируем обработчики
router.add_handler([](const HttpRequest& req) {
if (req.path == "/api/users" && req.method == "GET") {
handle_get_users();
return true; // Обработали
}
return false; // Не наш запрос
});

router.add_handler([](const HttpRequest& req) {
if (req.path.starts_with("/api/")) {
return handle_api_request(req);
}
return false;
});

// В главном цикле
void process_request(const HttpRequest& req) {
if (!router.handle(req)) {
send_404_error();
}
}


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

#шаблонный_код
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8👏2🎉21🌚1
🔥 Inline static в классах — забудь про .cpp

Сколько раз ты забывал добавить определение static члена в .cpp, и компилятор радостно выдавал undefined reference?


С C++17 можно просто добавить inline к static переменной класса, и всё работает. Особенно круто это для счётчиков, кешей и паттерна Registry.

// До C++17
class Logger {
public:
static std::ofstream log_file; // объявление
static int message_count; // объявление
};
// В .cpp обязательно нужны определения:
// std::ofstream Logger::log_file{"app.log"};
// int Logger::message_count = 0;

// С C++17
class Logger {
public:
inline static std::ofstream log_file{"app.log"};
inline static int message_count = 0;
inline static std::mutex log_mutex;

static void log(const std::string& msg) {
std::lock_guard lock(log_mutex);
log_file << "[" << message_count++ << "] " << msg << '\n';
}
};
// Никаких дополнительных файлов!


❗️Теперь весь класс может жить в заголовочном файле, что идеально для template классов и header-only библиотек. Инициализация происходит при первом использовании, потокобезопасно и предсказуемо.

🐸 Рефактори свои старые классы — убери лишние .cpp файлы и наслаждайся чистым кодом.

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

#шаблонный_код
Please open Telegram to view this post
VIEW IN TELEGRAM
👍181