PupStlCpp17.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <optional>
7 #include <pup_stl.h>
8 #include <utility>
9 #include <variant>
10 
11 #include "Utilities/Gsl.hpp"
12 #include "Utilities/TMPL.hpp"
13 
14 namespace PUP {
15 /// \ingroup ParallelGroup
16 /// Serialization of std::optional for Charm++
17 template <typename T>
18 void pup(er& p, std::optional<T>& t) noexcept { // NOLINT
19  bool valid = false;
20  if (p.isUnpacking()) {
21  p | valid;
22  if (valid) {
23  // default construct in a manner that doesn't require a copy.
24  // This is necessary when holding objects like pair<const Key, unique_ptr>
25  // in unordered map-type structures. The reason this case is tricky is
26  // because the const Key is non-movable while the unique_ptr is
27  // non-copyable. Our only option is in-place construction.
28  t.emplace();
29  p | *t;
30  } else {
31  t.reset();
32  }
33  } else {
34  valid = t.has_value();
35  p | valid;
36  if (valid) {
37  p | *t;
38  }
39  }
40 }
41 
42 /// \ingroup ParallelGroup
43 /// Serialization of std::optional for Charm++
44 template <typename T>
45 void operator|(er& p, std::optional<T>& t) noexcept { // NOLINT
46  pup(p, t);
47 }
48 
49 /// \ingroup ParallelGroup
50 /// Serialization of std::variant for Charm++
51 template <typename... Ts>
52 void pup(er& p, std::variant<Ts...>& t) noexcept { // NOLINT
53  // clang tidy: complains about pointer decay, I don't understand the error
54  // since nothing here is doing anything with pointers.
55  assert(not t.valueless_by_exception()); // NOLINT
56 
57  size_t current_index = 0;
58  size_t send_index = t.index();
59  p | send_index;
60 
61  const auto pup_helper = [&current_index, &p, send_index,
62  &t](auto type_v) noexcept {
63  using type = tmpl::type_from<decltype(type_v)>;
64  if (UNLIKELY(current_index == send_index)) {
65  if (p.isUnpacking()) {
66  type temp{};
67  p | temp;
68  t = std::move(temp);
69  } else {
70  p | std::get<type>(t);
71  }
72  }
73  ++current_index;
74  };
75  EXPAND_PACK_LEFT_TO_RIGHT(pup_helper(tmpl::type_<Ts>{}));
76 }
77 
78 /// \ingroup ParallelGroup
79 /// Serialization of std::variant for Charm++
80 template <typename... Ts>
81 void operator|(er& p, std::variant<Ts...>& t) noexcept { // NOLINT
82  pup(p, t);
83 }
84 } // namespace PUP
EXPAND_PACK_LEFT_TO_RIGHT
#define EXPAND_PACK_LEFT_TO_RIGHT(...)
Expand a parameter pack evaluating the terms from left to right.
Definition: TMPL.hpp:563
utility
UNLIKELY
#define UNLIKELY(x)
Definition: Gsl.hpp:73
Gsl.hpp
optional
TMPL.hpp
variant