Skip to content

Commit d313bec

Browse files
committed
Add compile-time base class chain introspection using any_cast_base
- Introduced type_list<Ts...> to represent type chains at compile time. - Implemented compute_base_chain_impl<T> to recursively collect base types based on any_cast_base<T> specializations. - Added get_base_chain_type_index<T>() to convert the chain into std::vector<std::type_index> for runtime use. - Supports safe termination when base is void or self-referential.
1 parent 6f0c367 commit d313bec

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

include/behaviortree_cpp/utils/safe_any.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,61 @@ struct is_polymorphic_safe<T, std::enable_if_t<is_complete<T>::value>>
116116
template <typename T>
117117
inline constexpr bool is_polymorphic_safe_v = is_polymorphic_safe<T>::value;
118118

119+
// Compute and store the base class inheritance chain of a type T
120+
// from derived to root base order, e.g. SphynxCat -> Cat -> Animal
121+
template <typename... Ts>
122+
struct type_list
123+
{
124+
template <typename U>
125+
using prepend = type_list<U, Ts...>;
126+
};
127+
128+
template <typename... Ts>
129+
std::vector<std::type_index> to_type_index_vector(type_list<Ts...>)
130+
{
131+
return { std::type_index(typeid(Ts))... };
132+
}
133+
134+
template <typename T, typename = void>
135+
struct compute_base_chain_impl
136+
{
137+
using type = type_list<T>;
138+
};
139+
140+
// Base case: recursion ends when base is void or equal to self
141+
template <typename T>
142+
struct compute_base_chain_impl<
143+
T, std::enable_if_t<std::is_same_v<typename any_cast_base<T>::type, void> ||
144+
std::is_same_v<typename any_cast_base<T>::type, T>>>
145+
{
146+
using type = type_list<T>;
147+
};
148+
149+
// Recursive case
150+
template <typename T>
151+
struct compute_base_chain_impl<
152+
T, std::enable_if_t<has_valid_cast_base<T>::value &&
153+
!std::is_same_v<typename any_cast_base<T>::type, void> &&
154+
!std::is_same_v<typename any_cast_base<T>::type, T> &&
155+
is_polymorphic_safe_v<T>>>
156+
{
157+
private:
158+
using Base = typename any_cast_base<T>::type;
159+
using BaseChain = typename compute_base_chain_impl<Base>::type;
160+
161+
public:
162+
using type = typename BaseChain::template prepend<T>;
163+
};
164+
165+
template <typename T>
166+
using compute_base_chain = typename compute_base_chain_impl<T>::type;
167+
168+
template <typename T>
169+
std::vector<std::type_index> get_base_chain_type_index()
170+
{
171+
return to_type_index_vector(compute_base_chain<T>{});
172+
}
173+
119174
// Rational: since type erased numbers will always use at least 8 bytes
120175
// it is faster to cast everything to either double, uint64_t or int64_t.
121176
class Any

0 commit comments

Comments
 (0)