Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cassert>
7 : #include <optional>
8 : #include <pup_stl.h>
9 : #include <utility>
10 : #include <variant>
11 :
12 : #include "Utilities/Gsl.hpp"
13 : #include "Utilities/TMPL.hpp"
14 :
15 : namespace PUP {
16 : /// \ingroup ParallelGroup
17 : /// Serialization of std::optional for Charm++
18 : template <typename T>
19 : void pup(er& p, std::optional<T>& t) { // NOLINT
20 : bool valid = false;
21 : if (p.isUnpacking()) {
22 : p | valid;
23 : if (valid) {
24 : // default construct in a manner that doesn't require a copy.
25 : // This is necessary when holding objects like pair<const Key, unique_ptr>
26 : // in unordered map-type structures. The reason this case is tricky is
27 : // because the const Key is non-movable while the unique_ptr is
28 : // non-copyable. Our only option is in-place construction.
29 : t.emplace();
30 : p | *t;
31 : } else {
32 : t.reset();
33 : }
34 : } else {
35 : valid = t.has_value();
36 : p | valid;
37 : if (valid) {
38 : p | *t;
39 : }
40 : }
41 : }
42 :
43 : /// \ingroup ParallelGroup
44 : /// Serialization of std::optional for Charm++
45 : template <typename T>
46 : void operator|(er& p, std::optional<T>& t) { // NOLINT
47 : pup(p, t);
48 : }
49 :
50 : /// \ingroup ParallelGroup
51 : /// Serialization of std::variant for Charm++
52 : template <typename... Ts>
53 : void pup(er& p, std::variant<Ts...>& t) { // NOLINT
54 : // clang tidy: complains about pointer decay, I don't understand the error
55 : // since nothing here is doing anything with pointers.
56 : assert(not t.valueless_by_exception()); // NOLINT
57 :
58 : size_t current_index = 0;
59 : size_t send_index = t.index();
60 : p | send_index;
61 :
62 : const auto pup_helper = [¤t_index, &p, send_index, &t](auto type_v) {
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) { // NOLINT
82 : pup(p, t);
83 : }
84 : } // namespace PUP
|