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