C++ Design Patterns
Apply design patterns in modern C++ — using templates, RAII, and modern features instead of traditional inheritance-heavy patterns.
50 min•By Priygop Team•Last updated: Feb 2026
Modern C++ Patterns
- Singleton (Meyers'): static MyClass& instance() { static MyClass inst; return inst; } — thread-safe in C++11+. Use sparingly, prefer dependency injection
- Observer (Signal/Slot): Type-safe callback system — std::function<void(EventData)> callbacks. Boost.Signals2 for thread-safe implementation
- Strategy (Policy Classes): template<class HashPolicy> class HashMap — compile-time strategy selection. Zero overhead vs virtual function dispatch
- Builder (Fluent API): auto config = Config::builder().setPort(8080).setHost('localhost').build(); — chainable methods returning *this reference
- Visitor (std::variant + std::visit): std::visit(overloaded{...}, variant) — type-safe pattern matching without virtual functions. Modern C++ replacement for traditional visitor
- Factory (std::unique_ptr): unique_ptr<Base> create(Type t) — returns ownership to caller. No raw new/delete. Registration-based factories for extensibility
Error Handling Strategies
- Exceptions: throw/try/catch for exceptional cases — constructor failures, out-of-memory, invalid operations. Zero cost when not thrown (table-based unwinding)
- std::expected<T, E> (C++23): Return value OR error — like Rust's Result<T, E>. Explicit error handling without exceptions. Perfect for expected failure paths
- Error Codes: Return error codes for performance-critical paths — avoid exception overhead in hot loops. Use enum class for type-safe error codes
- assert / static_assert: assert(condition) for runtime invariants (debug only). static_assert(condition) for compile-time checks (always active). Document assumptions
- noexcept: Mark functions that never throw — enables compiler optimizations (move operations, vector reallocation). Incorrect noexcept = std::terminate on exception