Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <type_traits> 7 : #include <typeinfo> 8 : #include <utility> 9 : 10 : #include "TypeTraits/FastPointerCast.hpp" 11 : #include "Utilities/ErrorHandling/Error.hpp" 12 : #include "Utilities/PrettyType.hpp" 13 : #include "Utilities/Requires.hpp" 14 : #include "Utilities/TMPL.hpp" 15 : 16 : /// \ingroup UtilitiesGroup 17 : /// \brief Call a functor with the derived type of a base class pointer. 18 : /// 19 : /// \details Calls functor with obj cast to type `T*` where T is the 20 : /// dynamic type of `*obj`. The decay type of `T` must be in the 21 : /// provided list of classes. 22 : /// 23 : /// \tparam Result the return type 24 : /// \tparam Classes the typelist of derived classes 25 : template <typename Result, typename Classes, typename Base, typename Callable> 26 1 : Result call_with_dynamic_type(Base* const obj, Callable&& f) { 27 : if constexpr (tmpl::size<Classes>::value != 0) { 28 : using Derived = tmpl::front<Classes>; 29 : using DerivedPointer = tmpl::conditional_t<std::is_const<Base>::value, 30 : Derived const*, Derived*>; 31 : return typeid(*obj) == typeid(Derived) 32 : ? std::forward<Callable>(f)( 33 : tt::fast_pointer_cast<DerivedPointer>(obj)) 34 : : call_with_dynamic_type<Result, tmpl::pop_front<Classes>>( 35 : obj, std::forward<Callable>(f)); 36 : } else { 37 : ERROR("Class " << pretty_type::get_runtime_type_name(*obj) 38 : << " is not registered with " 39 : << pretty_type::get_name<std::remove_const_t<Base>>()); 40 : } 41 : }