SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - TaggedTuple.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 20.3 % 74 15
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <cstddef>
       7              : #include <functional>
       8              : #include <initializer_list>
       9              : #include <ostream>
      10              : #include <stack>
      11              : #include <string>
      12              : #include <utility>
      13              : 
      14              : #include "Utilities/ErrorHandling/Assert.hpp"
      15              : #include "Utilities/Gsl.hpp"
      16              : #include "Utilities/MakeWithValue.hpp"
      17              : #include "Utilities/Overloader.hpp"
      18              : #include "Utilities/PrettyType.hpp"
      19              : #include "Utilities/PrintHelpers.hpp"
      20              : #include "Utilities/SetNumberOfGridPoints.hpp"
      21              : #include "Utilities/TMPL.hpp"
      22              : 
      23              : /// \cond
      24              : namespace PUP {
      25              : class er;
      26              : }  // namespace PUP
      27              : /// \endcond
      28              : 
      29              : /*!
      30              :  * \brief Contains utilities for working with tuples
      31              :  */
      32            1 : namespace tuples {
      33              : 
      34              : namespace tuples_detail {
      35              : 
      36              : template <class T>
      37              : inline constexpr T&& forward(typename std::remove_reference<T>::type& t) {
      38              :   return static_cast<T&&>(t);
      39              : }
      40              : 
      41              : template <class T>
      42              : inline constexpr T&& forward(typename std::remove_reference<T>::type&& t) {
      43              :   static_assert(!std::is_lvalue_reference<T>::value,
      44              :                 "cannot forward an rvalue as an lvalue");
      45              :   return static_cast<T&&>(t);
      46              : }
      47              : 
      48              : template <class T, T...>
      49              : struct value_list {};
      50              : 
      51              : template <class...>
      52              : struct typelist {};
      53              : 
      54              : template <bool... Bs>
      55              : using all = typename std::is_same<
      56              :     value_list<bool, Bs...>,
      57              :     value_list<bool, (static_cast<void>(Bs), true)...>>::type;
      58              : 
      59              : struct no_such_type {
      60              :   no_such_type() = delete;
      61              :   no_such_type(no_such_type const& /*unused*/) = delete;
      62              :   no_such_type(no_such_type&& /*unused*/) = delete;
      63              :   ~no_such_type() = delete;
      64              :   no_such_type& operator=(no_such_type const& /*unused*/) = delete;
      65              :   no_such_type operator=(no_such_type&& /*unused*/) = delete;
      66              : };
      67              : 
      68              : namespace detail {
      69              : using std::swap;
      70              : 
      71              : template <class T, class S,
      72              :           bool = not std::is_void<T>::value and not std::is_void<S>::value>
      73              : struct is_swappable_with {
      74              :   template <class L, class R>
      75              :   static auto test_swap(int)
      76              :       -> decltype(swap(std::declval<L&>(), std::declval<R&>()));
      77              :   template <class L, class R>
      78              :   static tuples::tuples_detail::no_such_type test_swap(...);
      79              : 
      80              :   static const bool value =
      81              :       not std::is_same<decltype(test_swap<T, S>(0)),
      82              :                        tuples::tuples_detail::no_such_type>::value and
      83              :       not std::is_same<decltype(test_swap<S, T>(0)),
      84              :                        tuples::tuples_detail::no_such_type>::value;
      85              : };
      86              : 
      87              : template <class T, class S>
      88              : struct is_swappable_with<T, S, false> : std::false_type {};
      89              : }  // namespace detail
      90              : 
      91              : template <class T, class S>
      92              : using is_swappable_with = detail::is_swappable_with<T, S>;
      93              : 
      94              : template <typename... Ts>
      95              : constexpr char expand_pack(Ts&&... /*unused*/) {
      96              :   return '0';
      97              : }
      98              : }  // namespace tuples_detail
      99              : 
     100              : namespace tuples_detail {
     101              : template <class Tag, bool Ebo = std::is_empty<typename Tag::type>::value &&
     102              :                                 !__is_final(typename Tag::type)>
     103              : class TaggedTupleLeaf;
     104              : 
     105              : template <class T, bool B>
     106              : void swap(TaggedTupleLeaf<T, B>& lhs, TaggedTupleLeaf<T, B>& rhs) {
     107              :   using std::swap;
     108              :   swap(lhs.get_data(), rhs.get_data());
     109              : }
     110              : 
     111              : template <class Tag>
     112              : class TaggedTupleLeaf<Tag, false> {
     113              :   using value_type = typename Tag::type;
     114              :   value_type value_;
     115              : 
     116              :   template <class T>
     117              :   static constexpr bool can_bind_reference() {
     118              :     using rem_ref_value_type = typename std::remove_reference<value_type>::type;
     119              :     using rem_ref_T = typename std::remove_reference<T>::type;
     120              :     using is_lvalue_type = std::integral_constant<
     121              :         bool,
     122              :         std::is_lvalue_reference<T>::value or
     123              :             std::is_same<std::reference_wrapper<rem_ref_value_type>,
     124              :                          rem_ref_T>::value or
     125              :             std::is_same<std::reference_wrapper<typename std::remove_const<
     126              :                              rem_ref_value_type>::type>,
     127              :                          rem_ref_T>::value>;
     128              :     return not std::is_reference<value_type>::value or
     129              :            (std::is_lvalue_reference<value_type>::value and
     130              :             is_lvalue_type::value) or
     131              :            (std::is_rvalue_reference<value_type>::value and
     132              :             not std::is_lvalue_reference<T>::value);
     133              :   }
     134              : 
     135              :  public:
     136              :   // Tested in constexpr context in Unit.TaggedTuple.Ebo
     137              :   constexpr TaggedTupleLeaf() : value_() {
     138              :     static_assert(
     139              :         !std::is_reference<value_type>::value,
     140              :         "Cannot default construct a reference element in a TaggedTuple");
     141              :   }
     142              : 
     143              :   // clang-tidy: forwarding references can be bad
     144              :   template <
     145              :       class T,
     146              :       typename std::enable_if<
     147              :           !std::is_same<typename std::decay<T>::type, TaggedTupleLeaf>::value &&
     148              :           std::is_constructible<value_type, T>::value>::type* = nullptr>
     149              :   constexpr explicit TaggedTupleLeaf(T&& t)
     150              :       : value_(tuples_detail::forward<T>(t)) {
     151              :     static_assert(can_bind_reference<T>(),
     152              :                   "Cannot construct an lvalue reference with an rvalue");
     153              :   }
     154              : 
     155              :   constexpr TaggedTupleLeaf(TaggedTupleLeaf const& /*rhs*/) = default;
     156              :   constexpr TaggedTupleLeaf(TaggedTupleLeaf&& /*rhs*/) = default;
     157              :   constexpr TaggedTupleLeaf& operator=(TaggedTupleLeaf const& /*rhs*/) =
     158              :       default;
     159              :   constexpr TaggedTupleLeaf& operator=(TaggedTupleLeaf&& /*rhs*/) = default;
     160              : 
     161              :   ~TaggedTupleLeaf() = default;
     162              : 
     163              :   // Note: name get_data instead of get to enable structured binding support.
     164              :   constexpr value_type& get_data() { return value_; }
     165              :   constexpr const value_type& get_data() const { return value_; }
     166              : 
     167              :   bool swap(TaggedTupleLeaf& t) {
     168              :     using std::swap;
     169              :     swap(*this, t);
     170              :     return false;
     171              :   }
     172              : 
     173              :   // clang-tidy: runtime-references
     174              :   void pup(PUP::er& p) { p | value_; }  // NOLINT
     175              : };
     176              : 
     177              : template <class Tag>
     178              : class TaggedTupleLeaf<Tag, true> : private Tag::type {
     179              :   using value_type = typename Tag::type;
     180              : 
     181              :  public:
     182              :   constexpr TaggedTupleLeaf() : value_type{} {}
     183              : 
     184              :   template <
     185              :       class T,
     186              :       typename std::enable_if<
     187              :           !std::is_same<typename std::decay<T>::type, TaggedTupleLeaf>::value &&
     188              :           std::is_constructible<value_type, T&&>::value>::type* = nullptr>
     189              :   constexpr explicit TaggedTupleLeaf(T&& t)
     190              :       : value_type(tuples_detail::forward<T>(t)) {}
     191              : 
     192              :   constexpr TaggedTupleLeaf(TaggedTupleLeaf const& /*rhs*/) = default;
     193              :   constexpr TaggedTupleLeaf(TaggedTupleLeaf&& /*rhs*/) = default;
     194              :   constexpr TaggedTupleLeaf& operator=(TaggedTupleLeaf const& /*rhs*/) =
     195              :       default;
     196              :   constexpr TaggedTupleLeaf& operator=(TaggedTupleLeaf&& /*rhs*/) = default;
     197              : 
     198              :   ~TaggedTupleLeaf() = default;
     199              : 
     200              :   // Note: name get_data instead of get to enable structured binding support.
     201              :   constexpr value_type& get_data() { return static_cast<value_type&>(*this); }
     202              : 
     203              :   constexpr const value_type& get_data() const {
     204              :     return static_cast<const value_type&>(*this);
     205              :   }
     206              : 
     207              :   bool swap(TaggedTupleLeaf& t) {
     208              :     using std::swap;
     209              :     swap(*this, t);
     210              :     return false;
     211              :   }
     212              : 
     213              :   // NOLINTNEXTLINE(google-runtime-references)
     214              :   void pup(PUP::er& p) { p | static_cast<typename Tag::type&>(*this); }
     215              : };
     216              : 
     217              : struct disable_constructors {
     218              :   static constexpr bool enable_default() { return false; }
     219              :   static constexpr bool enable_explicit() { return false; }
     220              :   static constexpr bool enable_implicit() { return false; }
     221              : };
     222              : }  // namespace tuples_detail
     223              : 
     224              : /*!
     225              :  * \ingroup UtilitiesGroup
     226              :  * \brief An associative container that is indexed by structs
     227              :  *
     228              :  * A data structure that is indexed by Tags. A Tag is a struct that contains
     229              :  * a type alias named `type`, which is the type of the object stored with
     230              :  * index Tag.
     231              :  *
     232              :  * \tparam Tags the tags of the objects to be placed in the tuple
     233              :  */
     234              : template <class... Tags>
     235              : class TaggedTuple;
     236              : 
     237              : template <class Tag, class... Tags>
     238              : constexpr const typename Tag::type& get(const TaggedTuple<Tags...>& t);
     239              : template <class Tag, class... Tags>
     240              : constexpr typename Tag::type& get(TaggedTuple<Tags...>& t);
     241              : template <class Tag, class... Tags>
     242              : constexpr const typename Tag::type&& get(const TaggedTuple<Tags...>&& t);
     243              : template <class Tag, class... Tags>
     244              : constexpr typename Tag::type&& get(TaggedTuple<Tags...>&& t);
     245              : 
     246              : /*!
     247              :  * \brief Returns the type of the Tag
     248              :  */
     249              : template <class Tag>
     250            1 : using tag_type = typename Tag::type;
     251              : 
     252              : // clang-tidy: class does not define copy or move assignment (it does)
     253              : template <class... Tags>
     254            1 : class TaggedTuple : private tuples_detail::TaggedTupleLeaf<Tags>... {  // NOLINT
     255              :   template <class... Args>
     256            0 :   struct pack_is_TaggedTuple : std::false_type {};
     257              :   template <class... Args>
     258            0 :   struct pack_is_TaggedTuple<TaggedTuple<Args...>> : std::true_type {};
     259              : 
     260              :   template <bool EnableConstructor, class Dummy = void>
     261            0 :   struct args_constructor : tuples_detail::disable_constructors {};
     262              : 
     263              :   template <class Dummy>
     264            0 :   struct args_constructor<true, Dummy> {
     265            0 :     static constexpr bool enable_default() {
     266              :       return tuples_detail::all<
     267              :           std::is_default_constructible<tag_type<Tags>>::value...>::value;
     268              :     }
     269              : 
     270              :     template <class... Ts>
     271            0 :     static constexpr bool enable_explicit() {
     272              :       return tuples_detail::all<std::is_constructible<
     273              :                  tuples_detail::TaggedTupleLeaf<Tags>, Ts>::value...>::value and
     274              :              not tuples_detail::all<
     275              :                  std::is_convertible<Ts, tag_type<Tags>>::value...>::value;
     276              :     }
     277              :     template <class... Ts>
     278            0 :     static constexpr bool enable_implicit() {
     279              :       return tuples_detail::all<std::is_constructible<
     280              :                  tuples_detail::TaggedTupleLeaf<Tags>, Ts>::value...>::value and
     281              :              tuples_detail::all<
     282              :                  std::is_convertible<Ts, tag_type<Tags>>::value...>::value;
     283              :     }
     284              :   };
     285              : 
     286              :   // C++17 Draft 23.5.3.2 Assignment - helper aliases
     287            0 :   using is_copy_assignable =
     288              :       tuples_detail::all<std::is_copy_assignable<tag_type<Tags>>::value...>;
     289            0 :   using is_nothrow_copy_assignable = tuples_detail::all<
     290              :       std::is_nothrow_copy_assignable<tag_type<Tags>>::value...>;
     291            0 :   using is_move_assignable =
     292              :       tuples_detail::all<std::is_move_assignable<tag_type<Tags>>::value...>;
     293            0 :   using is_nothrow_move_assignable = tuples_detail::all<
     294              :       std::is_nothrow_move_assignable<tag_type<Tags>>::value...>;
     295              : 
     296              :   // clang-tidy: redundant declaration
     297              :   template <class Tag, class... LTags>
     298            0 :   friend constexpr const typename Tag::type& get(  // NOLINT
     299              :       const TaggedTuple<LTags...>& t);
     300              :   template <class Tag, class... LTags>
     301            0 :   friend constexpr typename Tag::type& get(  // NOLINT
     302              :       TaggedTuple<LTags...>& t);
     303              :   template <class Tag, class... LTags>
     304            0 :   friend constexpr const typename Tag::type&& get(  // NOLINT
     305              :       const TaggedTuple<LTags...>&& t);
     306              :   template <class Tag, class... LTags>
     307            0 :   friend constexpr typename Tag::type&& get(  // NOLINT
     308              :       TaggedTuple<LTags...>&& t);
     309              : 
     310              :  public:
     311            0 :   using tags_list = tmpl::list<Tags...>;
     312              : 
     313            0 :   static constexpr size_t size() { return sizeof...(Tags); }
     314              : 
     315              :   // clang-tidy: runtime-references
     316              :   // NOLINTNEXTLINE(google-runtime-references)
     317            0 :   void pup(PUP::er& p) {
     318              :     static_cast<void>(std::initializer_list<char>{
     319              :         (tuples_detail::TaggedTupleLeaf<Tags>::pup(p), '0')...});
     320              :   }
     321              : 
     322              :   // C++17 Draft 23.5.3.1 Construction
     323              :   template <bool Dummy = true, typename std::enable_if<args_constructor<
     324              :                                    Dummy>::enable_default()>::type* = nullptr>
     325            0 :   constexpr TaggedTuple() {}
     326              : 
     327            0 :   TaggedTuple(TaggedTuple const& /*rhs*/) = default;
     328            0 :   TaggedTuple(TaggedTuple&& /*rhs*/) = default;
     329              : 
     330              :   /*!
     331              :    * \brief Construct a TaggedTuple with Args
     332              :    * \requires `std::is_convertible_v<Us, typename Tags::type>...` is `true`
     333              :    *
     334              :    * \example
     335              :    * \snippet Test_TaggedTuple.cpp construction_example
     336              :    */
     337              :   template <class... Us,
     338              :             typename std::enable_if<
     339              :                 args_constructor<not pack_is_TaggedTuple<Us...>::value and
     340              :                                  sizeof...(Us) == sizeof...(Tags)>::
     341              :                     template enable_explicit<Us...>()>::type* = nullptr>
     342            1 :   constexpr explicit TaggedTuple(Us&&... us)
     343              :       : tuples_detail::TaggedTupleLeaf<Tags>(
     344              :             tuples_detail::forward<Us>(us))... {}
     345              : 
     346              :   /*!
     347              :    * \brief Construct a TaggedTuple with Args
     348              :    * \requires `std::is_convertible_v<Us, typename Tags::type>...` is `true`
     349              :    *
     350              :    * \example
     351              :    * \snippet Test_TaggedTuple.cpp construction_example
     352              :    */
     353              :   template <class... Us,
     354              :             typename std::enable_if<
     355              :                 args_constructor<not pack_is_TaggedTuple<Us...>::value and
     356              :                                  sizeof...(Us) == sizeof...(Tags)>::
     357              :                     template enable_implicit<Us...>()>::type* = nullptr>
     358              :   // clang-tidy: mark explicit
     359            1 :   constexpr TaggedTuple(Us&&... us)
     360              :       : tuples_detail::TaggedTupleLeaf<Tags>(
     361              :             tuples_detail::forward<Us>(us))... {}
     362              : 
     363              :   template <
     364              :       class... UTags,
     365              :       typename std::enable_if<
     366              :           sizeof...(Tags) == sizeof...(UTags) and
     367              :           tuples_detail::all<std::is_constructible<
     368              :               tag_type<Tags>, const tag_type<UTags>&>::value...>::value and
     369              :           not tuples_detail::all<std::is_same<Tags, UTags>::value...>::value>::
     370              :           type* = nullptr>
     371            0 :   constexpr explicit TaggedTuple(TaggedTuple<UTags...> const& t)
     372              :       : tuples_detail::TaggedTupleLeaf<Tags>(get<UTags>(t))... {}
     373              : 
     374              :   template <class... UTags,
     375              :             typename std::enable_if<
     376              :                 sizeof...(Tags) == sizeof...(UTags) and
     377              :                 tuples_detail::all<std::is_constructible<
     378              :                     tag_type<Tags>, tag_type<UTags>&&>::value...>::value and
     379              :                 not tuples_detail::all<std::is_same<Tags, UTags>::value...>::
     380              :                     value>::type* = nullptr>
     381            0 :   constexpr explicit TaggedTuple(TaggedTuple<UTags...>&& t)
     382              :       : tuples_detail::TaggedTupleLeaf<Tags>(std::move(get<UTags>(t)))... {}
     383              : 
     384            0 :   ~TaggedTuple() = default;
     385              : 
     386              :   // C++17 Draft 23.5.3.2 Assignment
     387            0 :   TaggedTuple& operator=(
     388              :       tmpl::conditional_t<is_copy_assignable::value, TaggedTuple,
     389              :                           tuples_detail::no_such_type> const& t) {
     390              :     static_cast<void>(
     391              :         tuples_detail::expand_pack((get<Tags>(*this) = get<Tags>(t))...));
     392              :     return *this;
     393              :   }
     394              : 
     395            0 :   TaggedTuple& operator=(
     396              :       tmpl::conditional_t<is_move_assignable::value, TaggedTuple,
     397              :                           tuples_detail::no_such_type>&& t) {
     398              :     static_cast<void>(tuples_detail::expand_pack(
     399              :         (get<Tags>(*this) =
     400              :              tuples_detail::forward<tag_type<Tags>>(get<Tags>(t)))...));
     401              :     return *this;
     402              :   }
     403              : 
     404              :   template <class... UTags,
     405              :             typename std::enable_if<
     406              :                 sizeof...(Tags) == sizeof...(UTags) and
     407              :                 tuples_detail::all<std::is_assignable<
     408              :                     tag_type<Tags>&,
     409              :                     tag_type<UTags> const&>::value...>::value>::type* = nullptr>
     410            0 :   TaggedTuple& operator=(TaggedTuple<UTags...> const& t) {
     411              :     static_cast<void>(
     412              :         tuples_detail::expand_pack((get<Tags>(*this) = get<UTags>(t))...));
     413              :     return *this;
     414              :   }
     415              : 
     416              :   template <
     417              :       class... UTags,
     418              :       typename std::enable_if<
     419              :           sizeof...(Tags) == sizeof...(UTags) and
     420              :           tuples_detail::all<std::is_assignable<
     421              :               tag_type<Tags>&, tag_type<UTags>&&>::value...>::value>::type* =
     422              :           nullptr>
     423            0 :   TaggedTuple& operator=(TaggedTuple<UTags...>&& t) {
     424              :     static_cast<void>(tuples_detail::expand_pack(
     425              :         (get<Tags>(*this) =
     426              :              tuples_detail::forward<tag_type<UTags>>(get<UTags>(t)))...));
     427              :     return *this;
     428              :   }
     429              : 
     430              :   // C++17 Draft 23.5.3.3 swap
     431            0 :   void swap(TaggedTuple& t) {
     432              :     tuples_detail::expand_pack(tuples_detail::TaggedTupleLeaf<Tags>::swap(
     433              :         static_cast<tuples_detail::TaggedTupleLeaf<Tags>&>(t))...);
     434              :   }
     435              : };
     436              : 
     437              : template <>
     438            0 : class TaggedTuple<> {
     439              :  public:
     440            0 :   using tags_list = tmpl::list<>;
     441            0 :   static constexpr size_t size() { return 0; }
     442            0 :   TaggedTuple() = default;
     443            0 :   void swap(TaggedTuple& /*unused*/) {}
     444              :   // clang-tidy: runtime-references
     445            0 :   void pup(PUP::er& /*p*/) {}  // NOLINT
     446              : };
     447              : 
     448              : // C++17 Draft 23.5.3.6 Tuple helper classes
     449              : template <class T>
     450            0 : struct tuple_size;
     451              : 
     452              : template <class... Tags>
     453            0 : struct tuple_size<TaggedTuple<Tags...>>
     454              :     : std::integral_constant<size_t, sizeof...(Tags)> {};
     455              : template <class... Tags>
     456            0 : struct tuple_size<const TaggedTuple<Tags...>>
     457              :     : tuple_size<TaggedTuple<Tags...>> {};
     458              : template <class... Tags>
     459            0 : struct tuple_size<volatile TaggedTuple<Tags...>>
     460              :     : tuple_size<TaggedTuple<Tags...>> {};
     461              : template <class... Tags>
     462            0 : struct tuple_size<const volatile TaggedTuple<Tags...>>
     463              :     : tuple_size<TaggedTuple<Tags...>> {};
     464              : 
     465              : // C++17 Draft 23.5.3.7 Element access
     466              : /// @{
     467              : /*!
     468              :  * \ingroup UtilitiesGroup
     469              :  * \brief Retrieve the element of `Tag` in the TaggedTuple
     470              :  */
     471              : template <class Tag, class... Tags>
     472            1 : inline constexpr const typename Tag::type& get(const TaggedTuple<Tags...>& t) {
     473              :   static_assert(std::is_base_of<tuples_detail::TaggedTupleLeaf<Tag>,
     474              :                                 TaggedTuple<Tags...>>::value,
     475              :                 "Could not retrieve Tag from TaggedTuple. See the first "
     476              :                 "template parameter of the instantiation for what Tag is being "
     477              :                 "retrieved and the remaining template parameters for what Tags "
     478              :                 "are available.");
     479              :   return static_cast<const tuples_detail::TaggedTupleLeaf<Tag>&>(t).get_data();
     480              : }
     481              : template <class Tag, class... Tags>
     482            1 : inline constexpr typename Tag::type& get(TaggedTuple<Tags...>& t) {
     483              :   static_assert(std::is_base_of<tuples_detail::TaggedTupleLeaf<Tag>,
     484              :                                 TaggedTuple<Tags...>>::value,
     485              :                 "Could not retrieve Tag from TaggedTuple. See the first "
     486              :                 "template parameter of the instantiation for what Tag is being "
     487              :                 "retrieved and the remaining template parameters for what Tags "
     488              :                 "are available.");
     489              :   return static_cast<tuples_detail::TaggedTupleLeaf<Tag>&>(t).get_data();
     490              : }
     491              : template <class Tag, class... Tags>
     492            1 : inline constexpr const typename Tag::type&& get(
     493              :     const TaggedTuple<Tags...>&& t) {
     494              :   static_assert(std::is_base_of<tuples_detail::TaggedTupleLeaf<Tag>,
     495              :                                 TaggedTuple<Tags...>>::value,
     496              :                 "Could not retrieve Tag from TaggedTuple. See the first "
     497              :                 "template parameter of the instantiation for what Tag is being "
     498              :                 "retrieved and the remaining template parameters for what Tags "
     499              :                 "are available.");
     500              :   return static_cast<const typename Tag::type&&>(
     501              :       static_cast<const tuples_detail::TaggedTupleLeaf<Tag>&&>(t).get_data());
     502              : }
     503              : template <class Tag, class... Tags>
     504            1 : inline constexpr typename Tag::type&& get(TaggedTuple<Tags...>&& t) {
     505              :   static_assert(std::is_base_of<tuples_detail::TaggedTupleLeaf<Tag>,
     506              :                                 TaggedTuple<Tags...>>::value,
     507              :                 "Could not retrieve Tag from TaggedTuple. See the first "
     508              :                 "template parameter of the instantiation for what Tag is being "
     509              :                 "retrieved and the remaining template parameters for what Tags "
     510              :                 "are available.");
     511              :   return static_cast<typename Tag::type&&>(
     512              :       static_cast<tuples_detail::TaggedTupleLeaf<Tag>&&>(t).get_data());
     513              : }
     514              : /// @}
     515              : 
     516              : template <size_t I, class... Tags>
     517            0 : inline constexpr typename tmpl::at_c<tmpl::list<Tags...>, I>::type&& get(
     518              :     TaggedTuple<Tags...>&& t) {
     519              :   return get<tmpl::at_c<tmpl::list<Tags...>, I>>(t);
     520              : }
     521              : 
     522              : template <size_t I, class... Tags>
     523            0 : inline constexpr const typename tmpl::at_c<tmpl::list<Tags...>, I>::type& get(
     524              :     const TaggedTuple<Tags...>& t) {
     525              :   return get<tmpl::at_c<tmpl::list<Tags...>, I>>(t);
     526              : }
     527              : 
     528              : template <size_t I, class... Tags>
     529            0 : inline constexpr typename tmpl::at_c<tmpl::list<Tags...>, I>::type& get(
     530              :     TaggedTuple<Tags...>& t) {
     531              :   return get<tmpl::at_c<tmpl::list<Tags...>, I>>(t);
     532              : }
     533              : 
     534              : // C++17 Draft 23.5.3.8 Relational operators
     535              : namespace tuples_detail {
     536              : struct equal {
     537              :   template <class T, class U>
     538              :   static constexpr void apply(T const& lhs, U const& rhs, bool* result) {
     539              :     *result = *result and lhs == rhs;
     540              :   }
     541              : };
     542              : 
     543              : template <class... LTags, class... RTags>
     544              : constexpr bool tuple_equal_impl(TaggedTuple<LTags...> const& lhs,
     545              :                                 TaggedTuple<RTags...> const& rhs) {
     546              :   bool equal = true;
     547              :   // This short circuits in the sense that the operator== is only evaluated if
     548              :   // the result thus far is true
     549              :   static_cast<void>(std::initializer_list<char>{
     550              :       (equal::apply(get<LTags>(lhs), get<RTags>(rhs), &equal), '0')...});
     551              :   return equal;
     552              : }
     553              : }  // namespace tuples_detail
     554              : 
     555              : template <class... LTags, class... RTags,
     556              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     557              :               nullptr>
     558            0 : constexpr bool operator==(TaggedTuple<LTags...> const& lhs,
     559              :                           TaggedTuple<RTags...> const& rhs) {
     560              :   return tuples_detail::tuple_equal_impl(lhs, rhs);
     561              : }
     562              : 
     563              : template <class... LTags, class... RTags,
     564              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     565              :               nullptr>
     566            0 : constexpr bool operator!=(TaggedTuple<LTags...> const& lhs,
     567              :                           TaggedTuple<RTags...> const& rhs) {
     568              :   return not(lhs == rhs);
     569              : }
     570              : 
     571              : namespace tuples_detail {
     572              : struct less {
     573              :   template <class T, class U>
     574              :   static constexpr void apply(T const& lhs, U const& rhs,
     575              :                               bool* last_rhs_less_lhs, bool* result) {
     576              :     if (*result or *last_rhs_less_lhs) {
     577              :       return;
     578              :     }
     579              :     *result = lhs < rhs;
     580              :     if (*result) {
     581              :       return;
     582              :     }
     583              :     *last_rhs_less_lhs = rhs < lhs;
     584              :   }
     585              : };
     586              : 
     587              : template <class... LTags, class... RTags>
     588              : constexpr bool tuple_less_impl(TaggedTuple<LTags...> const& lhs,
     589              :                                TaggedTuple<RTags...> const& rhs) {
     590              :   bool result = false;
     591              :   bool last_rhs_less_lhs = false;
     592              :   static_cast<void>(
     593              :       std::initializer_list<char>{(less::apply(get<LTags>(lhs), get<RTags>(rhs),
     594              :                                                &last_rhs_less_lhs, &result),
     595              :                                    '0')...});
     596              :   return result;
     597              : }
     598              : }  // namespace tuples_detail
     599              : 
     600              : template <class... LTags, class... RTags,
     601              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     602              :               nullptr>
     603            0 : constexpr bool operator<(TaggedTuple<LTags...> const& lhs,
     604              :                          TaggedTuple<RTags...> const& rhs) {
     605              :   return tuples_detail::tuple_less_impl(lhs, rhs);
     606              : }
     607              : 
     608              : template <class... LTags, class... RTags,
     609              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     610              :               nullptr>
     611            0 : constexpr bool operator>(TaggedTuple<LTags...> const& lhs,
     612              :                          TaggedTuple<RTags...> const& rhs) {
     613              :   return rhs < lhs;
     614              : }
     615              : 
     616              : template <class... LTags, class... RTags,
     617              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     618              :               nullptr>
     619            0 : constexpr bool operator<=(TaggedTuple<LTags...> const& lhs,
     620              :                           TaggedTuple<RTags...> const& rhs) {
     621              :   return not(rhs < lhs);
     622              : }
     623              : 
     624              : template <class... LTags, class... RTags,
     625              :           typename std::enable_if<sizeof...(LTags) == sizeof...(RTags)>::type* =
     626              :               nullptr>
     627            0 : constexpr bool operator>=(TaggedTuple<LTags...> const& lhs,
     628              :                           TaggedTuple<RTags...> const& rhs) {
     629              :   return not(lhs < rhs);
     630              : }
     631              : 
     632              : // C++17 Draft 23.5.3.3 swap
     633              : template <
     634              :     class... Tags,
     635              :     typename std::enable_if<tuples_detail::all<tuples_detail::is_swappable_with<
     636              :         tuples_detail::TaggedTupleLeaf<Tags>,
     637              :         tuples_detail::TaggedTupleLeaf<Tags>>::value...>::value>::type* =
     638              :         nullptr>
     639            0 : void swap(TaggedTuple<Tags...>& lhs, TaggedTuple<Tags...>& rhs) {
     640              :   lhs.swap(rhs);
     641              : }
     642              : 
     643              : namespace TaggedTuple_detail {
     644              : template <typename T>
     645              : struct tagged_tuple_typelist_impl;
     646              : 
     647              : template <template <typename...> class List, typename... Tags>
     648              : struct tagged_tuple_typelist_impl<List<Tags...>> {
     649              :   using type = TaggedTuple<Tags...>;
     650              : };
     651              : }  // namespace TaggedTuple_detail
     652              : 
     653              : /// \ingroup UtilitiesGroup
     654              : template <typename T>
     655            0 : using tagged_tuple_from_typelist =
     656              :     typename TaggedTuple_detail::tagged_tuple_typelist_impl<T>::type;
     657              : 
     658              : namespace TaggedTuple_detail {
     659              : template <typename... InputTags, typename... OutputTags>
     660              : TaggedTuple<OutputTags...> reorder_impl(TaggedTuple<InputTags...>&& input,
     661              :                                         tmpl::list<OutputTags...> /*meta*/) {
     662              :   static_assert(
     663              :       std::is_same_v<tmpl::list_difference<tmpl::list<OutputTags...>,
     664              :                                            tmpl::list<InputTags...>>,
     665              :                      tmpl::list<>> and
     666              :           std::is_same_v<tmpl::list_difference<tmpl::list<InputTags...>,
     667              :                                                tmpl::list<OutputTags...>>,
     668              :                          tmpl::list<>>,
     669              :       "The input and output TaggedTuples must be the same except "
     670              :       "for ordering.");
     671              :   return TaggedTuple<OutputTags...>(std::move(get<OutputTags>(input))...);
     672              : }
     673              : }  // namespace TaggedTuple_detail
     674              : 
     675              : /// Given an input TaggedTuple, produce an output TaggedTuple
     676              : /// with the tags in a different order.  All tags must be the same
     677              : /// except for ordering.
     678              : /// \example
     679              : /// \snippet Test_TaggedTuple.cpp reorder_example
     680              : template <typename ReturnedTaggedTuple, typename... Tags>
     681            1 : ReturnedTaggedTuple reorder(TaggedTuple<Tags...> input) {
     682              :   return TaggedTuple_detail::reorder_impl(
     683              :       std::move(input), typename ReturnedTaggedTuple::tags_list{});
     684              : }
     685              : 
     686              : /// Stream operator for TaggedTuple
     687              : using ::operator<<;
     688              : template <class... Tags>
     689            0 : std::ostream& operator<<(std::ostream& os, const TaggedTuple<Tags...>& t) {
     690              :   os << "TaggedTuple:\n";
     691              :   const auto print_item = [&os, &t](auto tag_v) {
     692              :     using tag = tmpl::type_from<decltype(tag_v)>;
     693              :     using type = typename tag::type;
     694              :     os << "----------\n";
     695              :     os << "Name:  " << pretty_type::get_name<tag>() << "\n";
     696              :     os << "Type:  " << pretty_type::get_name<type>() << "\n";
     697              :     os << "Value: ";
     698              :     print_value(os, get<tag>(t));
     699              :     os << "\n";
     700              :   };
     701              :   tmpl::for_each<tmpl::list<Tags...>>(print_item);
     702              :   return os;
     703              : }
     704              : 
     705              : namespace TaggedTuple_detail {
     706              : 
     707              : template <typename F, typename... Tags, typename... ApplyTags>
     708              : constexpr decltype(auto) apply_impl(F&& f, const TaggedTuple<Tags...>& t,
     709              :                                     tmpl::list<ApplyTags...> /* meta */) {
     710              :   return std::forward<F>(f)(get<ApplyTags>(t)...);
     711              : }
     712              : 
     713              : }  // namespace TaggedTuple_detail
     714              : 
     715              : /// @{
     716              : /*!
     717              :  * \ingroup UtilitiesGroup
     718              :  * \brief Invoke `f` with the `ApplyTags` taken from `t` expanded in a parameter
     719              :  * pack
     720              :  *
     721              :  * `ApplyTags` defaults to the full list of tags in `t`.
     722              :  *
     723              :  * Here is an example how to use the function:
     724              :  *
     725              :  * \snippet Test_TaggedTuple.cpp expand_tuple_example
     726              :  *
     727              :  * This is the function being called in the above example:
     728              :  *
     729              :  * \snippet Test_TaggedTuple.cpp expand_tuple_example_function
     730              :  *
     731              :  * \see std::apply
     732              :  */
     733              : template <typename ApplyTags, typename F, typename... Tags>
     734            1 : constexpr decltype(auto) apply(F&& f, const TaggedTuple<Tags...>& t) {
     735              :   return TaggedTuple_detail::apply_impl(std::forward<F>(f), t, ApplyTags{});
     736              : }
     737              : 
     738              : template <typename F, typename... Tags>
     739            1 : constexpr decltype(auto) apply(F&& f, const TaggedTuple<Tags...>& t) {
     740              :   return TaggedTuple_detail::apply_impl(
     741              :       std::forward<F>(f), t, typename TaggedTuple<Tags...>::tags_list{});
     742              : }
     743              : /// @}
     744              : 
     745              : /// @{
     746              : /*!
     747              :  * Constructs a TaggedTuple that is a concatenation of two TaggedTuples.
     748              :  * \example
     749              :  * \snippet Test_TaggedTuple.cpp tagged_tuple_cat_example
     750              :  */
     751              : template <typename... Tags1, typename... Tags2>
     752            1 : tuples::TaggedTuple<Tags1..., Tags2...> tagged_tuple_cat(
     753              :     const tuples::TaggedTuple<Tags1...>& tuple1,
     754              :     const tuples::TaggedTuple<Tags2...>& tuple2) {
     755              :   return {get<Tags1>(tuple1)..., get<Tags2>(tuple2)...};
     756              : }
     757              : 
     758              : template <typename... Tags1, typename... Tags2>
     759            1 : tuples::TaggedTuple<Tags1..., Tags2...> tagged_tuple_cat(
     760              :     tuples::TaggedTuple<Tags1...>&& tuple1,
     761              :     tuples::TaggedTuple<Tags2...>&& tuple2) {
     762              :   return {std::move(get<Tags1>(tuple1))..., std::move(get<Tags2>(tuple2))...};
     763              : }
     764              : /// @}
     765              : 
     766              : }  // namespace tuples
     767              : 
     768              : namespace MakeWithValueImpls {
     769              : /// \brief Makes a `TaggedTuple`; each element of the `TaggedTuple`
     770              : /// must be `make_with_value`-creatable from a `T`.
     771              : template <typename... Tags, typename T>
     772            1 : struct MakeWithValueImpl<tuples::TaggedTuple<Tags...>, T> {
     773              :   template <typename ValueType>
     774            0 :   static SPECTRE_ALWAYS_INLINE tuples::TaggedTuple<Tags...> apply(
     775              :       const T& input, const ValueType value) {
     776              :     return tuples::TaggedTuple<Tags...>(
     777              :         make_with_value<typename Tags::type>(input, value)...);
     778              :   }
     779              : };
     780              : 
     781              : template <typename Tag, typename... Tags>
     782            0 : struct NumberOfPoints<tuples::TaggedTuple<Tag, Tags...>> {
     783            0 :   static SPECTRE_ALWAYS_INLINE size_t apply(
     784              :       const tuples::TaggedTuple<Tag, Tags...>& input) {
     785              :     const size_t points = number_of_points(tuples::get<Tag>(input));
     786              :     ASSERT((... and (number_of_points(tuples::get<Tags>(input)) == points)),
     787              :            "Inconsistent number of points in tuple entries.");
     788              :     return points;
     789              :   }
     790              : };
     791              : }  // namespace MakeWithValueImpls
     792              : 
     793              : template <typename... Tags>
     794            0 : struct SetNumberOfGridPointsImpls::SetNumberOfGridPointsImpl<
     795              :     tuples::TaggedTuple<Tags...>> {
     796            0 :   static constexpr bool is_trivial =
     797              :       (... and SetNumberOfGridPointsImpl<typename Tags::type>::is_trivial);
     798            0 :   static void apply(const gsl::not_null<tuples::TaggedTuple<Tags...>*> result,
     799              :                     const size_t size) {
     800              :     expand_pack((set_number_of_grid_points(
     801              :                      make_not_null(&tuples::get<Tags>(*result)), size),
     802              :                  0)...);
     803              :   }
     804              : };
     805              : 
     806              : namespace std {
     807              : template <typename... Tags>
     808              : struct tuple_size<tuples::TaggedTuple<Tags...>>
     809              :     : std::integral_constant<int, sizeof...(Tags)> {};
     810              : template <size_t I, typename... Tags>
     811              : struct tuple_element<I, tuples::TaggedTuple<Tags...>> {
     812              :   using type = typename tmpl::at_c<tmpl::list<Tags...>, I>::type;
     813              : };
     814              : }  // namespace std
        

Generated by: LCOV version 2.0-1