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

Generated by: LCOV version 1.14