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 :
8 : #include "DataStructures/DataBox/DataBox.hpp"
9 : #include "DataStructures/TempBuffer.hpp"
10 : #include "Utilities/Gsl.hpp"
11 : #include "Utilities/Requires.hpp"
12 : #include "Utilities/TMPL.hpp"
13 : #include "Utilities/TypeTraits/IsA.hpp"
14 :
15 : /// @{
16 : /*!
17 : * \ingroup DataStructuresGroup
18 : * \brief Retrieves a desired tag from data structures containing tags.
19 : *
20 : * \details Given multiple containers retrieve a desired tag from the first
21 : * container in which it is found. The containers are searched in the order
22 : * in which they are supplied (i.e. `first_vars` is checked before `vars`).
23 : * An error will be emitted if the tag cannot be found in any container.
24 : */
25 : template <typename Tag, typename... TagsOrTagsList, typename... Ts,
26 : template <class...> class U,
27 : Requires<(not tt::is_a_v<gsl::not_null, U<TagsOrTagsList...>>)and not(
28 : ... and tt::is_a_v<gsl::not_null, std::decay_t<Ts>>)> = nullptr>
29 1 : const typename Tag::type& get(const U<TagsOrTagsList...>& first_vars,
30 : const Ts&... vars) {
31 : if constexpr (tt::is_a_v<db::DataBox, U<TagsOrTagsList...>>) {
32 : if constexpr (not db::tag_is_retrievable_v<Tag, U<TagsOrTagsList...>> and
33 : sizeof...(Ts) != 0) {
34 : return get<Tag>(vars...);
35 : } else {
36 : return get<Tag>(first_vars);
37 : }
38 : } else {
39 : if constexpr (not tmpl::list_contains_v<
40 : tmpl::flatten<tmpl::list<TagsOrTagsList...>>, Tag> and
41 : sizeof...(Ts) != 0) {
42 : return get<Tag>(vars...);
43 : } else {
44 : return get<Tag>(first_vars);
45 : }
46 : }
47 : }
48 :
49 : template <typename Tag, typename... TagsOrTagsList, typename... Ts,
50 : template <class...> class U>
51 1 : gsl::not_null<typename Tag::type*> get(
52 : const gsl::not_null<U<TagsOrTagsList...>*> first_vars,
53 : const gsl::not_null<Ts>... vars) {
54 : if constexpr (tt::is_a_v<db::DataBox, U<TagsOrTagsList...>>) {
55 : if constexpr (not db::tag_is_retrievable_v<Tag, U<TagsOrTagsList...>> and
56 : sizeof...(Ts) != 0) {
57 : if constexpr (sizeof...(Ts) == 1) {
58 : return make_not_null(&get<Tag>(*vars...));
59 : } else {
60 : return get<Tag>(vars...);
61 : }
62 : } else {
63 : return make_not_null(&get<Tag>(*first_vars));
64 : }
65 : } else {
66 : if constexpr (not tmpl::list_contains_v<
67 : tmpl::flatten<tmpl::list<TagsOrTagsList...>>, Tag> and
68 : sizeof...(Ts) != 0) {
69 : (void)first_vars;
70 : if constexpr (sizeof...(Ts) == 1) {
71 : return make_not_null(&get<Tag>(*vars...));
72 : } else {
73 : return get<Tag>(vars...);
74 : }
75 : } else {
76 : return make_not_null(&get<Tag>(*first_vars));
77 : }
78 : }
79 : }
80 : /// @}
81 :
82 : namespace detail {
83 : template <typename Callable, typename T, typename... Args,
84 : typename... ReturnTags, typename... ArgumentTags>
85 : auto apply_impl([[maybe_unused]] const gsl::not_null<T*> return_args,
86 : tmpl::list<ReturnTags...> /*meta*/,
87 : tmpl::list<ArgumentTags...> /*meta*/, Callable&& fn,
88 : const Args&... args) {
89 : return fn.apply(get<ReturnTags>(return_args)...,
90 : get<ArgumentTags>(args...)...);
91 : }
92 :
93 : template <typename Callable, typename T, typename... Args,
94 : typename... ReturnTags, typename... ArgumentTags>
95 : auto invoke_impl([[maybe_unused]] const gsl::not_null<T*> return_args,
96 : tmpl::list<ReturnTags...> /*meta*/,
97 : tmpl::list<ArgumentTags...> /*meta*/, Callable&& fn,
98 : const Args&... args) {
99 : return fn(get<ReturnTags>(return_args)..., get<ArgumentTags>(args...)...);
100 : }
101 : } // namespace detail
102 :
103 : /*!
104 : * \brief Call
105 : * `fn.apply(get<Callable::return_tags>(return_args)...,
106 : * get<Callable::argument_tags>(args...))`
107 : */
108 : template <typename Callable, typename T, typename... Args>
109 1 : auto apply(const gsl::not_null<T*> return_args, Callable&& fn,
110 : const Args&... args) {
111 : return detail::apply_impl(return_args, typename Callable::return_tags{},
112 : typename Callable::argument_tags{},
113 : std::forward<Callable>(fn), args...);
114 : }
115 :
116 : /*!
117 : * \brief Call
118 : * `fn(get<Callable::return_tags>(return_args)...,
119 : * get<Callable::argument_tags>(args...))`
120 : */
121 : template <typename Callable, typename T, typename... Args>
122 1 : auto invoke(const gsl::not_null<T*> return_args, Callable&& fn,
123 : const Args&... args) {
124 : return detail::invoke_impl(return_args, typename Callable::return_tags{},
125 : typename Callable::argument_tags{},
126 : std::forward<Callable>(fn), args...);
127 : }
|