Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
adapter.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
12#pragma once
13
14#include <atomic>
15#include <memory>
16#include <optional>
17#include <stdexcept>
18#include <string>
19#include <type_traits>
20
22
23// Forward declarations
24class adapter_base;
25
26template<typename T>
27struct adapter_traits;
28
33template<typename T>
35 using value_type = T;
36 using pointer_type = T*;
37 using reference_type = T&;
38 using const_reference_type = const T&;
39 static constexpr bool is_smart_pointer = false;
40 static constexpr bool supports_weak = false;
41};
42
46template<typename T>
47struct adapter_traits<std::shared_ptr<T>> {
48 using value_type = T;
49 using pointer_type = std::shared_ptr<T>;
50 using reference_type = T&;
51 using const_reference_type = const T&;
52 using weak_type = std::weak_ptr<T>;
53 static constexpr bool is_smart_pointer = true;
54 static constexpr bool supports_weak = true;
55};
56
60template<typename T, typename Deleter>
61struct adapter_traits<std::unique_ptr<T, Deleter>> {
62 using value_type = T;
63 using pointer_type = std::unique_ptr<T, Deleter>;
64 using reference_type = T&;
65 using const_reference_type = const T&;
66 static constexpr bool is_smart_pointer = true;
67 static constexpr bool supports_weak = false;
68};
69
74public:
75 virtual ~adapter_base() = default;
76
81 virtual size_t get_adapter_depth() const = 0;
82
87 virtual bool is_adapter() const { return true; }
88
93 virtual size_t get_type_id() const = 0;
94};
95
117template<typename T, typename Traits = adapter_traits<T>>
118class adapter {
119public:
120 using value_type = typename Traits::value_type;
121 using pointer_type = typename Traits::pointer_type;
122 using reference_type = typename Traits::reference_type;
123 using const_reference_type = typename Traits::const_reference_type;
124
129 explicit adapter(T value) : value_(std::move(value)) {}
130
134 adapter() requires std::is_default_constructible_v<T> : value_() {}
135
140 auto get() const noexcept {
141 if constexpr (Traits::is_smart_pointer) {
142 return value_.get();
143 } else {
144 return std::addressof(value_);
145 }
146 }
147
152 decltype(auto) operator*() const {
153 if constexpr (Traits::is_smart_pointer) {
154 return *value_;
155 } else {
156 return value_;
157 }
158 }
159
163 decltype(auto) operator*() {
164 if constexpr (Traits::is_smart_pointer) {
165 return *value_;
166 } else {
167 return value_;
168 }
169 }
170
175 auto operator->() const noexcept { return get(); }
176
180 auto operator->() noexcept { return get(); }
181
186 auto weak() const requires(Traits::supports_weak) {
187 return typename Traits::weak_type(value_);
188 }
189
194 explicit operator bool() const noexcept {
195 if constexpr (Traits::is_smart_pointer) {
196 return static_cast<bool>(value_);
197 } else {
198 return true; // Value types are always valid
199 }
200 }
201
206 const T& value() const& noexcept { return value_; }
207
211 T& value() & noexcept { return value_; }
212
216 T value() && noexcept { return std::move(value_); }
217
222 T release() noexcept { return std::move(value_); }
223
228 static constexpr bool is_smart_pointer() noexcept {
229 return Traits::is_smart_pointer;
230 }
231
236 static constexpr bool supports_weak() noexcept {
237 return Traits::supports_weak;
238 }
239
240private:
242};
243
244// Deduction guides
245template<typename T>
247
248template<typename T>
249adapter(std::shared_ptr<T>) -> adapter<std::shared_ptr<T>>;
250
251template<typename T, typename D>
252adapter(std::unique_ptr<T, D>) -> adapter<std::unique_ptr<T, D>>;
253
262template<typename T, typename... Args>
263auto make_adapter(Args&&... args) {
264 return adapter<T>(T(std::forward<Args>(args)...));
265}
266
275template<typename T, typename... Args>
276auto make_shared_adapter(Args&&... args) {
277 return adapter(std::make_shared<T>(std::forward<Args>(args)...));
278}
279
288template<typename T, typename... Args>
289auto make_unique_adapter(Args&&... args) {
290 return adapter(std::make_unique<T>(std::forward<Args>(args)...));
291}
292
305template<typename Interface, typename Implementation>
306class interface_adapter : public Interface, public adapter_base {
307public:
313 explicit interface_adapter(std::shared_ptr<Implementation> impl)
314 : impl_(impl), wrapper_depth_(calculate_depth(impl)) {
316 throw std::runtime_error(
317 "Adapter chain too deep (" + std::to_string(wrapper_depth_) +
318 " levels, max: " + std::to_string(max_wrapper_depth_) + ")");
319 }
320 }
321
322 virtual ~interface_adapter() = default;
323
328 std::shared_ptr<Implementation> unwrap() const { return impl_; }
329
334 bool is_wrapped_adapter() const { return wrapper_depth_ > 0; }
335
340 size_t get_wrapper_depth() const { return wrapper_depth_; }
341
346 size_t get_adapter_depth() const override { return wrapper_depth_; }
347
352 static std::string adapter_type_name() {
353 return "interface_adapter<Interface, Implementation>";
354 }
355
360 static constexpr size_t max_depth() { return max_wrapper_depth_; }
361
366 size_t get_type_id() const override { return get_static_type_id(); }
367
372 static size_t get_static_type_id() {
373 static const size_t id = generate_type_id();
374 return id;
375 }
376
377protected:
378 std::shared_ptr<Implementation> impl_;
379
380private:
382 static constexpr size_t max_wrapper_depth_ = 2;
383
388 static size_t generate_type_id() {
389 static std::atomic<size_t> counter{0};
390 return ++counter;
391 }
392
398 static size_t calculate_depth(std::shared_ptr<Implementation> impl) {
399 if (!impl) {
400 return 0;
401 }
402
403 if constexpr (std::is_base_of_v<adapter_base, Implementation>) {
404#ifdef __cpp_rtti
405 if (auto* base_adapter =
406 dynamic_cast<adapter_base*>(impl.get())) {
407 return 1 + base_adapter->get_adapter_depth();
408 }
409 return 0;
410#else
411 auto* base_adapter = static_cast<adapter_base*>(impl.get());
412 if (base_adapter && base_adapter->get_type_id() != 0) {
413 return 1 + base_adapter->get_adapter_depth();
414 }
415 return 0;
416#endif
417 }
418
419 return 0;
420 }
421};
422
428template<typename T, typename Interface>
429inline constexpr bool implements_interface_v =
430 std::is_base_of_v<Interface, T> || std::is_convertible_v<T*, Interface*>;
431
441public:
453 template<typename Interface, typename Impl>
454 static std::shared_ptr<Interface>
455 create(std::shared_ptr<Impl> impl) {
457 return std::static_pointer_cast<Interface>(impl);
458 } else {
459 return std::make_shared<interface_adapter<Interface, Impl>>(impl);
460 }
461 }
462
471 template<typename AdapterType, typename... Args>
472 static std::shared_ptr<AdapterType> create_explicit(Args&&... args) {
473 return std::make_shared<AdapterType>(std::forward<Args>(args)...);
474 }
475
484 template<typename T, typename Interface>
485 static std::shared_ptr<T> try_unwrap(std::shared_ptr<Interface> ptr) {
486 if (!ptr) {
487 return nullptr;
488 }
489
490 if constexpr (std::is_base_of_v<adapter_base, Interface>) {
491#ifdef __cpp_rtti
492 if (auto* adapter =
493 dynamic_cast<interface_adapter<Interface, T>*>(ptr.get())) {
494 return adapter->unwrap();
495 }
496#else
497 auto* base = static_cast<adapter_base*>(ptr.get());
498 if (base && base->get_type_id() ==
500 auto* adapter =
501 static_cast<interface_adapter<Interface, T>*>(ptr.get());
502 return adapter->unwrap();
503 }
504#endif
505 }
506
507 return nullptr;
508 }
509
516 template<typename Interface, typename Impl>
517 static constexpr bool is_zero_cost() {
519 }
520};
521
529template<typename T, typename Interface>
530std::shared_ptr<T> safe_unwrap(std::shared_ptr<Interface> ptr) {
532}
533
540template<typename Interface>
541bool is_adapter(std::shared_ptr<Interface> ptr) {
542 if (!ptr) {
543 return false;
544 }
545
546 if constexpr (std::is_base_of_v<adapter_base, Interface>) {
547 auto* base = static_cast<adapter_base*>(ptr.get());
548 return base->is_adapter();
549 }
550
551 return false;
552}
553
562template<typename Interface, typename Impl>
563std::shared_ptr<Interface> make_interface_adapter(std::shared_ptr<Impl> impl) {
565}
566
575template<typename T, typename Interface>
576std::shared_ptr<T> unwrap_adapter(std::shared_ptr<Interface> ptr) {
578}
579
580} // namespace kcenon::common::adapters
Base class for adapter interface to eliminate RTTI dependency.
Definition adapter.h:73
virtual size_t get_type_id() const =0
Get unique type ID for this adapter type.
virtual size_t get_adapter_depth() const =0
Get the wrapper depth for this adapter.
virtual bool is_adapter() const
Check if this is an adapter (always true for adapter_base)
Definition adapter.h:87
Smart adapter factory that avoids unnecessary wrapping.
Definition adapter.h:440
static std::shared_ptr< AdapterType > create_explicit(Args &&... args)
Create an adapter with explicit adapter type.
Definition adapter.h:472
static std::shared_ptr< Interface > create(std::shared_ptr< Impl > impl)
Create an adapter with automatic optimization.
Definition adapter.h:455
static constexpr bool is_zero_cost()
Check if zero-cost adaptation is possible.
Definition adapter.h:517
static std::shared_ptr< T > try_unwrap(std::shared_ptr< Interface > ptr)
Try to unwrap an interface to get underlying implementation.
Definition adapter.h:485
Unified adapter template for wrapping values or smart pointers.
Definition adapter.h:118
static constexpr bool is_smart_pointer() noexcept
Check if adapter is holding a smart pointer type.
Definition adapter.h:228
T release() noexcept
Release ownership and return the underlying value.
Definition adapter.h:222
typename Traits::value_type value_type
Definition adapter.h:120
auto weak() const
Get weak reference (only for shared_ptr)
Definition adapter.h:186
typename Traits::pointer_type pointer_type
Definition adapter.h:121
typename Traits::reference_type reference_type
Definition adapter.h:122
adapter()
Default constructor (for default-constructible types)
Definition adapter.h:134
adapter(T value)
Construct adapter from value.
Definition adapter.h:129
auto operator->() const noexcept
Arrow operator.
Definition adapter.h:175
T & value() &noexcept
Get the underlying storage (mutable)
Definition adapter.h:211
T value() &&noexcept
Move out the underlying storage.
Definition adapter.h:216
auto operator->() noexcept
Arrow operator (mutable)
Definition adapter.h:180
typename Traits::const_reference_type const_reference_type
Definition adapter.h:123
auto get() const noexcept
Access raw pointer to the stored value.
Definition adapter.h:140
const T & value() const &noexcept
Get the underlying storage.
Definition adapter.h:206
static constexpr bool supports_weak() noexcept
Check if weak references are supported.
Definition adapter.h:236
Interface adapter with type safety and depth tracking.
Definition adapter.h:306
bool is_wrapped_adapter() const
Check if this adapter wraps another adapter.
Definition adapter.h:334
static std::string adapter_type_name()
Get type name for debugging.
Definition adapter.h:352
size_t get_type_id() const override
Get unique type ID for this adapter type.
Definition adapter.h:366
std::shared_ptr< Implementation > impl_
Definition adapter.h:378
interface_adapter(std::shared_ptr< Implementation > impl)
Construct adapter with existing implementation.
Definition adapter.h:313
static constexpr size_t max_depth()
Get the maximum allowed wrapper depth.
Definition adapter.h:360
static size_t calculate_depth(std::shared_ptr< Implementation > impl)
Calculate the depth of adapter wrapping.
Definition adapter.h:398
static size_t generate_type_id()
Generate a unique type ID.
Definition adapter.h:388
size_t get_adapter_depth() const override
Get the adapter depth (implements adapter_base)
Definition adapter.h:346
static constexpr size_t max_wrapper_depth_
Definition adapter.h:382
size_t get_wrapper_depth() const
Get the current wrapper depth.
Definition adapter.h:340
static size_t get_static_type_id()
Get static type ID for this adapter type.
Definition adapter.h:372
std::shared_ptr< Implementation > unwrap() const
Get the underlying implementation.
Definition adapter.h:328
auto make_adapter(Args &&... args)
Factory function to create adapter with in-place construction.
Definition adapter.h:263
auto make_unique_adapter(Args &&... args)
Factory function to create adapter wrapping unique_ptr.
Definition adapter.h:289
std::shared_ptr< Interface > make_interface_adapter(std::shared_ptr< Impl > impl)
Convenience function for creating smart adapters.
Definition adapter.h:563
std::shared_ptr< T > unwrap_adapter(std::shared_ptr< Interface > ptr)
Convenience function for unwrapping adapters.
Definition adapter.h:576
adapter(T) -> adapter< T >
std::shared_ptr< T > safe_unwrap(std::shared_ptr< Interface > ptr)
Helper function to safely unwrap an adapter.
Definition adapter.h:530
bool is_adapter(std::shared_ptr< Interface > ptr)
Check if an interface pointer is actually an adapter.
Definition adapter.h:541
constexpr bool implements_interface_v
Type trait to check if a type implements an interface.
Definition adapter.h:429
auto make_shared_adapter(Args &&... args)
Factory function to create adapter wrapping shared_ptr.
Definition adapter.h:276
Primary adapter_traits template for value types.
Definition adapter.h:34
static constexpr bool is_smart_pointer
Definition adapter.h:39
static constexpr bool supports_weak
Definition adapter.h:40