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

Generated by: LCOV version 1.14