@@ -36,6 +36,48 @@ struct any_cast_base
3636 using type = void ; // Default: no base known, fallback to default any storage
3737};
3838
39+ // C++17 backport of std::type_identity
40+ template <typename T>
41+ struct type_identity
42+ {
43+ using type = T;
44+ };
45+
46+ // Trait to check if a type has a valid cast base
47+ template <typename T, typename = void >
48+ struct has_valid_cast_base : std::false_type
49+ {
50+ };
51+
52+ template <typename T>
53+ struct has_valid_cast_base <T, std::void_t <typename any_cast_base<T>::type>>
54+ {
55+ static constexpr bool value =
56+ !std::is_same<typename any_cast_base<T>::type, void >::value;
57+ };
58+
59+ // Recursive helper (non-self-recursive, SFINAE-safe)
60+ template <typename T>
61+ struct resolve_root_base_helper
62+ {
63+ using Base = typename any_cast_base<T>::type;
64+
65+ using type = typename std::conditional<std::is_same<T, Base>::value, type_identity<T>,
66+ resolve_root_base_helper<Base>>::type::type;
67+ };
68+
69+ // Public interface with guard
70+ template <typename T>
71+ struct root_base_resolver
72+ {
73+ using type = typename std::conditional<has_valid_cast_base<T>::value,
74+ resolve_root_base_helper<T>,
75+ type_identity<T>>::type::type;
76+ };
77+
78+ template <typename T>
79+ using root_base_t = typename root_base_resolver<T>::type;
80+
3981// Trait to detect std::shared_ptr types.
4082template <typename T>
4183struct is_shared_ptr : std::false_type
@@ -160,9 +202,12 @@ class Any
160202 // store as base class if specialized
161203 if constexpr (!std::is_same_v<Base, void >)
162204 {
163- static_assert (is_polymorphic_safe_v<Base>, " Any Base trait specialization must be "
164- " polymorphic" );
165- _any = std::static_pointer_cast<Base>(value);
205+ using RootBase = root_base_t <T>;
206+
207+ static_assert (is_polymorphic_safe_v<RootBase>, " Any Base trait specialization must "
208+ " be "
209+ " polymorphic" );
210+ _any = std::static_pointer_cast<RootBase>(value);
166211 }
167212 else
168213 {
@@ -264,15 +309,17 @@ class Any
264309
265310 if constexpr (is_polymorphic_safe_v<Derived> && !std::is_same_v<Base, void >)
266311 {
312+ using RootBase = root_base_t <Derived>;
313+
267314 try
268315 {
269316 // Attempt to retrieve the stored shared_ptr<Base> from the Any container
270- auto base_ptr = linb::any_cast<std::shared_ptr<Base >>(&_any);
317+ auto base_ptr = linb::any_cast<std::shared_ptr<RootBase >>(&_any);
271318 if (!base_ptr)
272319 return nullptr ;
273320
274321 // Case 1: If Base and Derived are the same, no casting is needed
275- if constexpr (std::is_same_v<Base , Derived>)
322+ if constexpr (std::is_same_v<RootBase , Derived>)
276323 {
277324 return reinterpret_cast <T*>(base_ptr);
278325 }
@@ -636,15 +683,17 @@ inline nonstd::expected<T, std::string> Any::tryCast() const
636683
637684 if constexpr (is_polymorphic_safe_v<Derived> && !std::is_same_v<Base, void >)
638685 {
686+ using RootBase = root_base_t <Derived>;
687+
639688 // Attempt to retrieve the stored shared_ptr<Base> from the Any container
640- auto base_ptr = linb::any_cast<std::shared_ptr<Base >>(_any);
689+ auto base_ptr = linb::any_cast<std::shared_ptr<RootBase >>(_any);
641690 if (!base_ptr)
642691 {
643692 throw std::runtime_error (" Any::cast cannot cast to shared_ptr<Base> class" );
644693 }
645694
646695 // Case 1: If Base and Derived are the same, no casting is needed
647- if constexpr (std::is_same_v<T, std::shared_ptr<Base >>)
696+ if constexpr (std::is_same_v<T, std::shared_ptr<RootBase >>)
648697 {
649698 return base_ptr;
650699 }
0 commit comments