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 : /// Extra arguments can be passed by `const&` to the functor.
24 : ///
25 : /// \tparam Result the return type
26 : /// \tparam Classes the typelist of derived classes
27 : template <typename Result, typename Classes, typename Base, typename Callable,
28 : typename... Args>
29 1 : Result call_with_dynamic_type(Base* const obj, Callable&& f, Args&&... args) {
30 : if constexpr (tmpl::size<Classes>::value != 0) {
31 : using Derived = tmpl::front<Classes>;
32 : using DerivedPointer = tmpl::conditional_t<std::is_const<Base>::value,
33 : Derived const*, Derived*>;
34 : return typeid(*obj) == typeid(Derived)
35 : ? std::forward<Callable>(f)(
36 : tt::fast_pointer_cast<DerivedPointer>(obj),
37 : std::forward<Args>(args)...)
38 : : call_with_dynamic_type<Result, tmpl::pop_front<Classes>>(
39 : obj, std::forward<Callable>(f),
40 : std::forward<Args>(args)...);
41 : } else {
42 : ERROR("Class " << pretty_type::get_runtime_type_name(*obj)
43 : << " is not registered with "
44 : << pretty_type::get_name<std::remove_const_t<Base>>());
45 : }
46 : }
|