DataBoxTag.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines classes SimpleTag, PrefixTag, ComputeTag and several
6 /// functions for retrieving tag info
7 
8 #pragma once
9 
10 #include <cstddef>
11 #include <ostream>
12 #include <string>
13 
14 #include "ErrorHandling/Assert.hpp"
16 #include "Utilities/NoSuchType.hpp"
17 #include "Utilities/PrettyType.hpp"
18 #include "Utilities/Requires.hpp"
19 #include "Utilities/TMPL.hpp"
20 #include "Utilities/TypeTraits.hpp"
21 
22 /// \cond
23 namespace Tags {
24 template <typename TagsList>
25 struct Variables;
26 } // namespace Tags
27 /// \endcond
28 
29 namespace Tags {
30 /*!
31  * \ingroup DataBoxTagsGroup
32  * \brief Tag used to retrieve the DataBox from the `db::get` function
33  *
34  * The main use of this tag is to allow fetching the DataBox from itself. The
35  * primary use case is to allow an invokable to take a DataBox as an argument
36  * when called through `db::apply`.
37  *
38  * \snippet Test_DataBox.cpp databox_self_tag_example
39  */
40 struct DataBox {
41  // Trick to get friend function declaration to compile but a const void& is
42  // rather useless
43  using type = void;
44 };
45 } // namespace Tags
46 
47 namespace db {
48 /*!
49  * \ingroup DataBoxGroup
50  * \brief Tags for the DataBox inherit from this type
51  *
52  * \details
53  * Used to mark a type as being a SimpleTag so that it can be used in a
54  * DataBox.
55  *
56  * \derivedrequires
57  * - type alias `type` of the type this SimpleTag represents
58  * - static `std::string name()` method that returns a runtime name for the tag.
59  *
60  * \example
61  * \snippet Test_DataBox.cpp databox_tag_example
62  *
63  * \see DataBox PrefixTag get_tag_name
64  */
65 struct SimpleTag {};
66 
67 /*!
68  * \ingroup DataBoxGroup
69  * \brief Tags that are base tags, i.e. a simple or compute tag must derive
70  * off them for them to be useful
71  *
72  * Base tags do not need to contain type information, unlike simple
73  * tags which must contain the type information. Base tags are designed so
74  * that retrieving items from the DataBox or setting argument tags in compute
75  * items can be done without any knowledge of the type of the item.
76  *
77  * To use the base mechanism the base tag must inherit off of
78  * `BaseTag` and NOT `SimpleTag`. This is very important for the
79  * implementation. Inheriting off both and not making the tag either a simple
80  * item or compute item is undefined behavior and is likely to end in extremely
81  * complicated compiler errors.
82  */
83 struct BaseTag {};
84 
85 /*!
86  * \ingroup DataBoxGroup
87  * \brief Marks an item as being a prefix to another tag
88  *
89  * \details
90  * Used to mark a type as being a DataBoxTag where the `label` is a prefix to
91  * the DataBoxTag that is a member type alias `tag`. A prefix tag must contain a
92  * type alias named `type` with the type of the Tag it is a prefix to, as well
93  * as a type alias `tag` that is the type of the Tag that this prefix tag is
94  * a prefix for. A prefix tag must also have a `label` equal to the name of
95  * the struct (tag).
96  *
97  * \derivedrequires
98  * - type alias `tag` of the DataBoxTag that this tag is a prefix to
99  * - type alias `type` that is the type that this PrefixTag holds
100  * - static `std::string name()` method that returns a runtime name for the tag.
101  *
102  * \example
103  * A PrefixTag tag has the structure:
104  * \snippet Test_DataBox.cpp databox_prefix_tag_example
105  *
106  * The name used to retrieve a prefix tag from the DataBox is:
107  * \snippet Test_DataBox.cpp databox_name_prefix
108  *
109  *
110  * \see DataBox DataBoxTag get_tag_name ComputeTag
111  */
112 struct PrefixTag {};
113 
114 /*!
115  * \ingroup DataBoxGroup
116  * \brief Marks a DataBoxTag as being a compute item that executes a function
117  *
118  * \details
119  * Compute items come in two forms: mutating and non-mutating. Mutating
120  * compute items modify a stored value in order to reduce the number of memory
121  * allocations done. For example, if a function would return a `Variables` or
122  * `Tensor<DataVector...>` and is called every time step, then it would be
123  * preferable to use a mutating compute item so that the values in the already
124  * allocated memory can just be changed.
125  * In contrast, non-mutating compute items simply return the new value after a
126  * call (if the value is out-of-date), which is fine for infrequently called
127  * compute items or ones that do not allocate data on the heap.
128  *
129  * A compute item tag contains a member named `function` that is either a
130  * function pointer, or a static constexpr function. The compute item tag
131  * must also have a `label`, same as the DataBox tags, and a type alias
132  * `argument_tags` that is a typelist of the tags that will
133  * be retrieved from the DataBox and whose data will be passed to the function
134  * (pointer). Mutating compute item tags must also contain a type alias named
135  * `return_type` that is the type the function is mutating. The type must be
136  * default constructible.
137  *
138  * \example
139  * Most non-mutating compute item tags will look similar to:
140  * \snippet Test_DataBox.cpp databox_compute_item_tag_example
141  * Note that the arguments can be empty:
142  * \snippet Test_DataBox.cpp compute_item_tag_no_tags
143  *
144  * Mutating compute item tags are of the form:
145  * \snippet Test_DataBox.cpp databox_mutating_compute_item_tag
146  * where the function is:
147  * \snippet Test_DataBox.cpp databox_mutating_compute_item_function
148  *
149  * You can also have `function` be a function instead of a function pointer,
150  * which offers a lot of simplicity for very simple compute items.
151  * \snippet Test_DataBox.cpp compute_item_tag_function
152  *
153  * \see DataBox SimpleTag get_tag_name PrefixTag
154  */
155 struct ComputeTag {};
156 
157 namespace DataBox_detail {
158 template <typename TagList, typename Tag>
159 using list_of_matching_tags = tmpl::conditional_t<
160  cpp17::is_same_v<Tag, ::Tags::DataBox>, tmpl::list<::Tags::DataBox>,
161  tmpl::filter<TagList, std::is_base_of<tmpl::pin<Tag>, tmpl::_1>>>;
162 
163 template <typename TagList, typename Tag>
164 using first_matching_tag = tmpl::front<list_of_matching_tags<TagList, Tag>>;
165 
166 template <typename TagList, typename Tag>
167 constexpr auto number_of_matching_tags =
168  tmpl::size<list_of_matching_tags<TagList, Tag>>::value;
169 
170 template <typename TagList, typename Tag>
171 struct has_unique_matching_tag
172  : std::integral_constant<bool, number_of_matching_tags<TagList, Tag> == 1> {
173 };
174 
175 template <typename TagList, typename Tag>
176 using has_unique_matching_tag_t =
177  typename has_unique_matching_tag<TagList, Tag>::type;
178 
179 template <typename TagList, typename Tag>
180 constexpr bool has_unique_matching_tag_v =
181  has_unique_matching_tag<TagList, Tag>::value;
182 
183 template <typename TagList, typename Tag>
184 struct has_no_matching_tag
185  : std::integral_constant<bool, number_of_matching_tags<TagList, Tag> == 0> {
186 };
187 
188 template <typename TagList, typename Tag>
189 using has_no_matching_tag_t = typename has_no_matching_tag<TagList, Tag>::type;
190 
191 template <typename TagList, typename Tag>
192 constexpr bool has_no_matching_tag_v = has_no_matching_tag<TagList, Tag>::value;
193 } // namespace DataBox_detail
194 
195 /*!
196  * \ingroup DataBoxGroup
197  * \brief Get the name of a DataBoxTag, including prefixes
198  *
199  * \details
200  * Given a DataBoxTag returns the name of the DataBoxTag as a std::string. If
201  * the DataBoxTag is also a PrefixTag then the prefix is added.
202  *
203  * \tparam Tag the DataBoxTag whose name to get
204  * \return string holding the DataBoxTag's name
205  */
206 template <typename Tag>
208  return Tag::name();
209 }
210 
211 // @{
212 /*!
213  * \ingroup DataBoxGroup
214  * \brief Check if `Tag` derives off of db::ComputeTag
215  */
216 template <typename Tag, typename = std::nullptr_t>
218 /// \cond HIDDEN_SYMBOLS
219 template <typename Tag>
220 struct is_compute_item<Tag, Requires<cpp17::is_base_of_v<db::ComputeTag, Tag>>>
221  : std::true_type {};
222 /// \endcond
223 
224 template <typename Tag>
225 constexpr bool is_compute_item_v = is_compute_item<Tag>::value;
226 // @}
227 
228 // @{
229 /*!
230  * \ingroup DataBoxGroup
231  * \brief Check if `Tag` is a non-base DataBox tag. I.e. a SimpleTag or a
232  * ComputeTag
233  */
234 template <typename Tag, typename = std::nullptr_t>
236 /// \cond
237 template <typename Tag>
238 struct is_non_base_tag<Tag, Requires<cpp17::is_base_of_v<db::ComputeTag, Tag> or
239  cpp17::is_base_of_v<db::SimpleTag, Tag>>>
240  : std::true_type {};
241 /// \endcond
242 
243 template <typename Tag>
244 constexpr bool is_non_base_tag_v = is_non_base_tag<Tag>::value;
245 // @}
246 
247 // @{
248 /*!
249  * \ingroup DataBoxGroup
250  * \brief Check if `Tag` is a BaseTag, SimpleTag, or ComputeTag
251  */
252 template <typename Tag, typename = std::nullptr_t>
254 /// \cond
255 template <typename Tag>
256 struct is_tag<Tag, Requires<cpp17::is_base_of_v<db::ComputeTag, Tag> or
257  cpp17::is_base_of_v<db::SimpleTag, Tag> or
258  cpp17::is_base_of_v<db::BaseTag, Tag>>>
259  : std::true_type {};
260 /// \endcond
261 
262 template <typename Tag>
263 constexpr bool is_tag_v = is_tag<Tag>::value;
264 // @}
265 
266 // @{
267 /*!
268  * \ingroup DataBoxGroup
269  * \brief Check if `Tag` is a base DataBox tag
270  */
271 template <typename Tag, typename = std::nullptr_t>
273 /// \cond HIDDEN_SYMBOLS
274 template <typename Tag>
275 struct is_base_tag<Tag, Requires<cpp17::is_base_of_v<db::BaseTag, Tag> and
276  not cpp17::is_base_of_v<db::SimpleTag, Tag> and
277  not is_compute_item_v<Tag>>> : std::true_type {
278 };
279 /// \endcond
280 
281 template <typename Tag>
282 constexpr bool is_base_tag_v = is_base_tag<Tag>::value;
283 // @}
284 
285 template <class T, class = void>
287 template <class T>
288 struct has_return_type_member<T, cpp17::void_t<typename T::return_type>>
289  : std::true_type {};
290 
291 /*!
292  * \brief `true` if `T` has nested type alias named `return_type`
293  */
294 template <class T>
296 
297 namespace DataBox_detail {
298 template <typename TagList, typename Tag>
299 struct item_type_impl;
300 
301 template <int SelectTagType>
302 struct dispatch_item_type;
303 
304 template <typename ArgsList>
305 struct compute_item_type;
306 
307 template <typename TagList, typename Tag>
308 struct item_type_impl {
309  // item_type_impl is intentionally a lazy metafunction rather than a
310  // metaclosure or a metacontinuation. The reason is that it is quite likely we
311  // call `db::item_type<Tag>` multiple times within the same translation unit
312  // and so we want to memoize the resulting type. However, we do not want to
313  // memoize the dispatch calls.
314  using type = typename dispatch_item_type<
315  is_base_tag_v<Tag>
316  ? 4
317  : (is_compute_item_v<Tag>and has_return_type_member_v<Tag>)
318  ? 3
319  : is_compute_item_v<Tag>
320  ? 2
321  : cpp17::is_base_of_v<db::SimpleTag, Tag> ? 1 : 0>::
322  template f<TagList, Tag>;
323 };
324 
325 template <>
326 struct dispatch_item_type<0> {
327  // Tag is not a tag. This is necessary for SFINAE friendliness, specifically
328  // if someone calls Requires<tt::is_a_v<std::vector, db::item_type<Tag>>>
329  // with, say Tag = double, then this should probably SFINAE away, not fail to
330  // compile.
331  template <typename TagList, typename Tag>
332  using f = NoSuchType;
333 };
334 
335 template <>
336 struct dispatch_item_type<1> {
337  // simple item
338  template <typename TagList, typename Tag>
339  using f = typename Tag::type;
340 };
341 
342 template <>
343 struct dispatch_item_type<2> {
344  // compute item
345  template <typename TagList, typename Tag>
346  using f = typename compute_item_type<typename Tag::argument_tags>::template f<
347  TagList, Tag>;
348 };
349 
350 template <>
351 struct dispatch_item_type<3> {
352  // mutating compute item
353  template <typename TagList, typename Tag>
354  using f = typename Tag::return_type;
355 };
356 
357 template <>
358 struct dispatch_item_type<4> {
359  // base tag item: retrieve the derived tag from the tag list then call
360  // item_type_impl on the result.
361  // We do not check that there is only one matching tag in the DataBox because
362  // the uniqueness is only checked in get and mutate. The reason for that is
363  // that it is fine to have multiple derived tags in the DataBox as long as
364  // they all have the same type. We do not check that the types are all the
365  // same, it is undefined behavior if they are not and the user's
366  // responsibility.
367  template <typename TagList, typename Tag>
368  using f =
369  typename item_type_impl<TagList, first_matching_tag<TagList, Tag>>::type;
370 };
371 
372 CREATE_IS_CALLABLE(function)
373 
374 template <typename Tag, typename TagList, typename TagTypesList>
375 struct check_compute_item_is_invokable;
376 
377 template <typename Tag, typename... Tags, typename... TagTypes>
378 struct check_compute_item_is_invokable<Tag, tmpl::list<Tags...>,
379  tmpl::list<TagTypes...>> {
380  static_assert(
381  is_function_callable_v<Tag, TagTypes...>,
382  "The compute item is not callable with the types that the tags hold. The "
383  "compute item tag that is the problem should be shown in the first line "
384  " after the static assert error: "
385  "'check_compute_item_is_invokable<TheItemThatsFailingToBeCalled, "
386  "brigand::list<PassedTags...>, "
387  "brigand::list<item_type<PassedTags>...>>'");
388 };
389 
390 template <typename... Args>
391 struct compute_item_type<tmpl::list<Args...>> {
392  template <typename TagList, typename Tag>
393  using f = decltype(
394 #ifdef SPECTRE_DEBUG
395  (void)check_compute_item_is_invokable<
396  Tag, tmpl::list<Args...>,
397  tmpl::list<typename item_type_impl<TagList, Args>::type...>>{},
398 #endif // SPECTRE_DEBUG
399  Tag::function(
400  std::declval<typename item_type_impl<TagList, Args>::type>()...));
401 };
402 } // namespace DataBox_detail
403 
404 /*!
405  * \ingroup DataBoxGroup
406  * \brief Get the type that is returned by the `Tag`. If it is a base tag then a
407  * `TagList` must be passed as a second argument.
408  */
409 template <typename Tag, typename TagList = NoSuchType>
410 using item_type = typename DataBox_detail::item_type_impl<TagList, Tag>::type;
411 
412 /// \ingroup DataBoxTagsGroup
413 /// \brief Create a new list of Tags by wrapping each tag in `TagList` using the
414 /// `Wrapper`.
415 template <template <typename...> class Wrapper, typename TagList,
416  typename... Args>
417 using wrap_tags_in =
418  tmpl::transform<TagList, tmpl::bind<Wrapper, tmpl::_1, tmpl::pin<Args>...>>;
419 
420 namespace DataBox_detail {
421 enum class DispatchTagType {
422  Variables,
423  Prefix,
424  Other,
425 };
426 
427 template <typename Tag>
428 constexpr DispatchTagType tag_type =
429  tt::is_a_v<Tags::Variables, Tag>
430  ? DispatchTagType::Variables
431  : cpp17::is_base_of_v<db::PrefixTag, Tag> ? DispatchTagType::Prefix
432  : DispatchTagType::Other;
433 
434 template <DispatchTagType TagType>
435 struct add_tag_prefix_impl;
436 
437 // Call the appropriate impl based on the type of the tag being
438 // prefixed.
439 template <template <typename...> class Prefix, typename Tag, typename... Args>
440 using dispatch_add_tag_prefix_impl =
441  typename add_tag_prefix_impl<tag_type<Tag>>::template f<Prefix, Tag,
442  Args...>;
443 
444 template <>
445 struct add_tag_prefix_impl<DispatchTagType::Other> {
446  template <template <typename...> class Prefix, typename Tag, typename... Args>
447  using f = Tag;
448 };
449 
450 template <>
451 struct add_tag_prefix_impl<DispatchTagType::Prefix> {
452  template <template <typename...> class Prefix, typename Tag, typename... Args>
453  struct prefix_wrapper_helper;
454 
455  template <template <typename...> class Prefix,
456  template <typename...> class InnerPrefix, typename InnerTag,
457  typename... InnerArgs, typename... Args>
458  struct prefix_wrapper_helper<Prefix, InnerPrefix<InnerTag, InnerArgs...>,
459  Args...> {
460  static_assert(
461  cpp17::is_same_v<typename InnerPrefix<InnerTag, InnerArgs...>::tag,
462  InnerTag>,
463  "Inconsistent values of prefixed tag");
464  using type =
465  InnerPrefix<dispatch_add_tag_prefix_impl<Prefix, InnerTag, Args...>,
466  InnerArgs...>;
467  };
468 
469  template <template <typename...> class Prefix, typename Tag, typename... Args>
470  using f = typename prefix_wrapper_helper<Prefix, Tag, Args...>::type;
471 };
472 
473 template <>
474 struct add_tag_prefix_impl<DispatchTagType::Variables> {
475  template <template <typename...> class Prefix, typename Tag, typename... Args>
476  using f =
477  Tags::Variables<wrap_tags_in<Prefix, typename Tag::tags_list, Args...>>;
478 };
479 
480 // Implementation of remove_tag_prefix
481 template <typename>
482 struct remove_tag_prefix_impl;
483 
484 template <DispatchTagType TagType>
485 struct remove_variables_prefix;
486 
487 template <typename Tag>
488 using dispatch_remove_variables_prefix =
489  typename remove_variables_prefix<tag_type<Tag>>::template f<Tag>;
490 
491 template <>
492 struct remove_variables_prefix<DispatchTagType::Other> {
493  template <typename Tag>
494  using f = Tag;
495 };
496 
497 template <>
498 struct remove_variables_prefix<DispatchTagType::Prefix> {
499  template <typename Tag>
500  struct helper;
501 
502  template <template <typename...> class Prefix, typename Tag, typename... Args>
503  struct helper<Prefix<Tag, Args...>> {
504  using type = Prefix<dispatch_remove_variables_prefix<Tag>, Args...>;
505  };
506 
507  template <typename Tag>
508  using f = typename helper<Tag>::type;
509 };
510 
511 template <>
512 struct remove_variables_prefix<DispatchTagType::Variables> {
513  template <typename Tag>
514  using f = Tags::Variables<tmpl::transform<typename Tag::tags_list,
515  remove_tag_prefix_impl<tmpl::_1>>>;
516 };
517 
518 template <typename UnprefixedTag, template <typename...> class Prefix,
519  typename... Args>
520 struct remove_tag_prefix_impl<Prefix<UnprefixedTag, Args...>> {
521  static_assert(cpp17::is_base_of_v<db::SimpleTag, UnprefixedTag>,
522  "Unwrapped tag is not a DataBoxTag");
523  using type = dispatch_remove_variables_prefix<UnprefixedTag>;
524 };
525 } // namespace DataBox_detail
526 
527 /// \ingroup DataBoxTagsGroup
528 /// Wrap `Tag` in `Prefix<_, Args...>`, also wrapping variables tags
529 /// if `Tag` is a `Tags::Variables`.
530 template <template <typename...> class Prefix, typename Tag, typename... Args>
531 using add_tag_prefix =
532  Prefix<DataBox_detail::dispatch_add_tag_prefix_impl<Prefix, Tag, Args...>,
533  Args...>;
534 
535 /// \ingroup DataBoxTagsGroup
536 /// Remove a prefix from `Tag`, also removing it from the variables
537 /// tags if the unwrapped tag is a `Tags::Variables`.
538 template <typename Tag>
539 using remove_tag_prefix =
540  typename DataBox_detail::remove_tag_prefix_impl<Tag>::type;
541 
542 namespace DataBox_detail {
543 template <class Tag, bool IsPrefix>
544 struct remove_all_prefixes_impl;
545 } // namespace DataBox_detail
546 
547 /// \ingroup DataBoxGroup
548 /// Completely remove all prefix tags from a Tag
549 template <typename Tag>
550 using remove_all_prefixes = typename DataBox_detail::remove_all_prefixes_impl<
551  Tag, cpp17::is_base_of_v<db::PrefixTag, Tag>>::type;
552 
553 namespace DataBox_detail {
554 template <class Tag>
555 struct remove_all_prefixes_impl<Tag, false> {
556  using type = Tag;
557 };
558 
559 template <class Tag>
560 struct remove_all_prefixes_impl<Tag, true> {
562 };
563 
564 // Implementation of variables_tag_with_tags_list
565 template <DispatchTagType TagType>
566 struct variables_tag_with_tags_list_impl;
567 } // namespace DataBox_detail
568 
569 /// \ingroup DataBoxGroup
570 /// Change the tags contained in a possibly prefixed Variables tag.
571 /// \example
572 /// \snippet Test_DataBoxTag.cpp variables_tag_with_tags_list
573 template <typename Tag, typename NewTagsList>
575  typename DataBox_detail::variables_tag_with_tags_list_impl<
576  DataBox_detail::tag_type<Tag>>::template f<Tag, NewTagsList>;
577 
578 namespace DataBox_detail {
579 // Implementation of variables_tag_with_tags_list
580 template <>
581 struct variables_tag_with_tags_list_impl<DispatchTagType::Variables> {
582  template <typename Tag, typename NewTagsList>
584 };
585 
586 template <>
587 struct variables_tag_with_tags_list_impl<DispatchTagType::Prefix> {
588  template <typename Tag, typename NewTagsList>
589  struct helper;
590 
591  template <template <typename...> class Prefix, typename Tag, typename... Args,
592  typename NewTagsList>
593  struct helper<Prefix<Tag, Args...>, NewTagsList> {
594  using type =
595  Prefix<variables_tag_with_tags_list<Tag, NewTagsList>, Args...>;
596  };
597 
598  template <typename Tag, typename NewTagsList>
599  using f = typename helper<Tag, NewTagsList>::type;
600 };
601 
602 // Implementation of get_variables_tags_list
603 template <DispatchTagType TagType>
604 struct get_variables_tags_list_impl;
605 } // namespace DataBox_detail
606 
607 template <typename Tag>
608 using get_variables_tags_list =
609  typename DataBox_detail::get_variables_tags_list_impl<
610  DataBox_detail::tag_type<Tag>>::template f<Tag>;
611 
612 namespace DataBox_detail {
613 // Implementation of get_variables_tags_list
614 template <>
615 struct get_variables_tags_list_impl<DispatchTagType::Variables> {
616  template <typename Tag>
617  using f = typename Tag::tags_list;
618 };
619 
620 template <>
621 struct get_variables_tags_list_impl<DispatchTagType::Prefix> {
622  template <typename Tag>
623  using f = get_variables_tags_list<typename Tag::tag>;
624 };
625 } // namespace DataBox_detail
626 
627 /// \ingroup DataBoxGroup
628 /// Struct that can be specialized to allow DataBox items to have
629 /// subitems. Specializations must define:
630 /// * `using type = tmpl::list<...>` listing the subtags of `Tag`
631 /// * A static member function to initialize a subitem of a simple
632 /// item:
633 /// ```
634 /// template <typename Subtag>
635 /// static void create_item(
636 /// const gsl::not_null<item_type<Tag>*> parent_value,
637 /// const gsl::not_null<item_type<Subtag>*> sub_value) noexcept;
638 /// ```
639 /// Mutating the subitems must also modify the main item.
640 /// * A static member function evaluating a subitem of a compute
641 /// item:
642 /// ```
643 /// template <typename Subtag>
644 /// static item_type<Subtag> create_compute_item(
645 /// const item_type<Tag>& parent_value) noexcept;
646 /// ```
647 template <typename TagList, typename Tag, typename = std::nullptr_t>
648 struct Subitems {
649  using type = tmpl::list<>;
650 };
651 
652 /// \ingroup DataBoxGroup
653 /// Split a tag into its subitems. `Tag` cannot be a base tag.
654 template <typename Tag, typename TagList = NoSuchType>
655 using split_tag = tmpl::conditional_t<
656  tmpl::size<typename Subitems<TagList, Tag>::type>::value == 0,
657  tmpl::list<Tag>, typename Subitems<TagList, Tag>::type>;
658 } // namespace db
Prefix< DataBox_detail::dispatch_add_tag_prefix_impl< Prefix, Tag, Args... >, Args... > add_tag_prefix
Wrap Tag in Prefix<_, Args...>, also wrapping variables tags if Tag is a Tags::Variables.
Definition: DataBoxTag.hpp:533
Definition: Variables.hpp:46
Check if Tag is a BaseTag, SimpleTag, or ComputeTag.
Definition: DataBoxTag.hpp:253
#define CREATE_IS_CALLABLE(METHOD_NAME)
Generate a type trait to check if a class has a member function that can be invoked with arguments of...
Definition: TypeTraits.hpp:870
void void_t
Given a set of types, returns void
Definition: TypeTraits.hpp:214
Check if Tag is a non-base DataBox tag. I.e. a SimpleTag or a ComputeTag.
Definition: DataBoxTag.hpp:235
Marks a DataBoxTag as being a compute item that executes a function.
Definition: DataBoxTag.hpp:155
Check if Tag is a base DataBox tag.
Definition: DataBoxTag.hpp:272
Tags for the DataBox inherit from this type.
Definition: DataBoxTag.hpp:65
tmpl::conditional_t< tmpl::size< typename Subitems< TagList, Tag >::type >::value==0, tmpl::list< Tag >, typename Subitems< TagList, Tag >::type > split_tag
Split a tag into its subitems. Tag cannot be a base tag.
Definition: DataBoxTag.hpp:657
tmpl::transform< TagList, tmpl::bind< Wrapper, tmpl::_1, tmpl::pin< Args >... > > wrap_tags_in
Create a new list of Tags by wrapping each tag in TagList using the Wrapper.
Definition: DataBoxTag.hpp:418
std::string get_tag_name()
Get the name of a DataBoxTag, including prefixes.
Definition: DataBoxTag.hpp:207
Defines the type alias Requires.
typename DataBox_detail::remove_tag_prefix_impl< Tag >::type remove_tag_prefix
Remove a prefix from Tag, also removing it from the variables tags if the unwrapped tag is a Tags::Va...
Definition: DataBoxTag.hpp:540
Used to mark "no type" or "bad state" for metaprogramming.
Definition: NoSuchType.hpp:10
Tag used to retrieve the DataBox from the db::get function.
Definition: DataBoxTag.hpp:40
constexpr bool is_same_v
Variable template for is_same.
Definition: TypeTraits.hpp:221
typename DataBox_detail::variables_tag_with_tags_list_impl< DataBox_detail::tag_type< Tag > >::template f< Tag, NewTagsList > variables_tag_with_tags_list
Change the tags contained in a possibly prefixed Variables tag.
Definition: DataBoxTag.hpp:576
Struct that can be specialized to allow DataBox items to have subitems. Specializations must define: ...
Definition: DataBoxTag.hpp:648
Define simple functions for constant expressions.
Definition: DataBoxTag.hpp:29
typename DataBox_detail::remove_all_prefixes_impl< Tag, cpp17::is_base_of_v< db::PrefixTag, Tag > >::type remove_all_prefixes
Completely remove all prefix tags from a Tag.
Definition: DataBoxTag.hpp:551
Namespace for DataBox related things.
Definition: DataBox.hpp:33
Defines macro ASSERT.
Contains a pretty_type library to write types in a "pretty" format.
Wraps the template metaprogramming library used (brigand)
typename DataBox_detail::item_type_impl< TagList, Tag >::type item_type
Get the type that is returned by the Tag. If it is a base tag then a TagList must be passed as a seco...
Definition: DataBoxTag.hpp:410
Marks an item as being a prefix to another tag.
Definition: DataBoxTag.hpp:112
Tags that are base tags, i.e. a simple or compute tag must derive off them for them to be useful...
Definition: DataBoxTag.hpp:83
Defines type traits, some of which are future STL type_traits header.
Definition: DataBoxTag.hpp:286
constexpr bool has_return_type_member_v
true if T has nested type alias named return_type
Definition: DataBoxTag.hpp:295
Check if Tag derives off of db::ComputeTag.
Definition: DataBoxTag.hpp:217