SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - TaggedTuple.hpp Hit Total Coverage
Commit: 107e15b340886ae54549b1baa4bfc92e676f667e Lines: 15 74 20.3 %
Date: 2026-09-17 16:38:56
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 1.14