@@ -47,6 +47,33 @@ struct is_shared_ptr<std::shared_ptr<U>> : std::true_type
4747{
4848};
4949
50+ // Trait to detect if a type is complete
51+ template <typename T, typename = void >
52+ struct is_complete : std::false_type
53+ {
54+ };
55+
56+ template <typename T>
57+ struct is_complete <T, decltype (void (sizeof (T)))> : std::true_type
58+ {
59+ };
60+
61+ // Trait to detect if a trait is complete and polymorphic
62+ template <typename T, typename = void >
63+ struct is_polymorphic_safe : std::false_type
64+ {
65+ };
66+
67+ // Specialization only enabled if T is complete
68+ template <typename T>
69+ struct is_polymorphic_safe <T, std::enable_if_t <is_complete<T>::value>>
70+ : std::integral_constant<bool , std::is_polymorphic<T>::value>
71+ {
72+ };
73+
74+ template <typename T>
75+ inline constexpr bool is_polymorphic_safe_v = is_polymorphic_safe<T>::value;
76+
5077// Rational: since type erased numbers will always use at least 8 bytes
5178// it is faster to cast everything to either double, uint64_t or int64_t.
5279class Any
@@ -83,12 +110,12 @@ class Any
83110 };
84111
85112 template <typename T>
86- struct IsPolymorphicSharedPtr <T, std:: void_t < typename T::element_type>>
87- : std::integral_constant<
88- bool ,
89- is_shared_ptr<T>::value && std::is_polymorphic_v <typename T::element_type> &&
90- !std::is_same_v<typename any_cast_base<typename T::element_type>::type,
91- void >>
113+ struct IsPolymorphicSharedPtr <
114+ T,
115+ std:: enable_if_t <
116+ is_shared_ptr<T>::value && is_polymorphic_safe_v <typename T::element_type> &&
117+ !std::is_same_v<typename any_cast_base<typename T::element_type>::type, void >>>
118+ : std::true_type
92119 {
93120 };
94121
@@ -159,7 +186,7 @@ class Any
159186 // store as base class if specialized
160187 if constexpr (!std::is_same_v<Base, void >)
161188 {
162- static_assert (std::is_polymorphic_v <Base>, " Any Base trait specialization must be "
189+ static_assert (is_polymorphic_safe_v <Base>, " Any Base trait specialization must be "
163190 " polymorphic" );
164191 _any = std::static_pointer_cast<Base>(value);
165192 }
@@ -633,7 +660,7 @@ inline nonstd::expected<T, std::string> Any::tryCast() const
633660 using Derived = typename T::element_type;
634661 using Base = typename any_cast_base<Derived>::type;
635662
636- if constexpr (std::is_polymorphic_v <Derived> && !std::is_same_v<Base, void >)
663+ if constexpr (is_polymorphic_safe_v <Derived> && !std::is_same_v<Base, void >)
637664 {
638665 // Attempt to retrieve the stored shared_ptr<Base> from the Any container
639666 auto base_ptr = linb::any_cast<std::shared_ptr<Base>>(_any);
0 commit comments