@@ -36,6 +36,48 @@ struct any_cast_base
36
36
using type = void ; // Default: no base known, fallback to default any storage
37
37
};
38
38
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
+
39
81
// Trait to detect std::shared_ptr types.
40
82
template <typename T>
41
83
struct is_shared_ptr : std::false_type
@@ -160,9 +202,12 @@ class Any
160
202
// store as base class if specialized
161
203
if constexpr (!std::is_same_v<Base, void >)
162
204
{
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);
166
211
}
167
212
else
168
213
{
@@ -264,15 +309,17 @@ class Any
264
309
265
310
if constexpr (is_polymorphic_safe_v<Derived> && !std::is_same_v<Base, void >)
266
311
{
312
+ using RootBase = root_base_t <Derived>;
313
+
267
314
try
268
315
{
269
316
// 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);
271
318
if (!base_ptr)
272
319
return nullptr ;
273
320
274
321
// 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>)
276
323
{
277
324
return reinterpret_cast <T*>(base_ptr);
278
325
}
@@ -636,15 +683,17 @@ inline nonstd::expected<T, std::string> Any::tryCast() const
636
683
637
684
if constexpr (is_polymorphic_safe_v<Derived> && !std::is_same_v<Base, void >)
638
685
{
686
+ using RootBase = root_base_t <Derived>;
687
+
639
688
// 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);
641
690
if (!base_ptr)
642
691
{
643
692
throw std::runtime_error (" Any::cast cannot cast to shared_ptr<Base> class" );
644
693
}
645
694
646
695
// 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 >>)
648
697
{
649
698
return base_ptr;
650
699
}
0 commit comments