From a1306a62fc6e4190e42ba1ea820dbcb3f3169fd9 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Tue, 9 Jun 2020 11:25:47 +0200 Subject: [PATCH] Add serialization of std::variant --- ebos/eclmpiserializer.hh | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/ebos/eclmpiserializer.hh b/ebos/eclmpiserializer.hh index 86cd6a4dd..427a06c3b 100644 --- a/ebos/eclmpiserializer.hh +++ b/ebos/eclmpiserializer.hh @@ -22,6 +22,7 @@ #define ECL_MPI_SERIALIZER_HH #include +#include namespace Opm { @@ -48,6 +49,8 @@ public: ptr(data); } else if constexpr (is_pair::value) { pair(data); + } else if constexpr (is_variant::value) { + variant(data); } else { if (m_op == Operation::PACKSIZE) m_packSize += Mpi::packSize(data, m_comm); @@ -93,6 +96,54 @@ public: } } + + //! \brief Handler for std::variant<> with three types + + /* + The std::variant<> serialization is a first attempt and *not* particularly + general. In particular that implies: + + 1. It is hardcoded to hold exactly three alternative types T1, T2 and + T3. + + 2. All the three types T1, T2 and T3 must implement the ::serializeOp( ) + method. This implies that a variant with a fundamental type like e.g. + std::variant will *not* work in the + current implementation. + */ + template + void variant(const std::variant& _data) + { + auto handle = [&](auto& d) { + d.serializeOp(*this); + }; + + std::variant& data = const_cast&>(_data); + if (m_op == Operation::PACKSIZE) { + m_packSize += Mpi::packSize(data.index(), m_comm); + std::visit( [&] (auto& arg) { handle(arg); }, data); + } else if (m_op == Operation::PACK) { + Mpi::pack(data.index(), m_buffer, m_position, m_comm); + std::visit([&](auto& arg) { handle(arg); }, data); + } else if (m_op == Operation::UNPACK) { + size_t index; + Mpi::unpack(index, m_buffer, m_position, m_comm); + + if (index == 0) { + data = T1(); + handle(std::get<0>(data)); + } else if (index == 1) { + data = T2(); + handle(std::get<1>(data)); + } else if (index == 2) { + data = T3(); + handle(std::get<2>(data)); + } else + std::logic_error("Internal meltdown in std::variant unpack"); + } + } + + //! \brief Handler for maps. //! \tparam Map map type //! \tparam complexType Whether or not Data in map is a complex type @@ -232,6 +283,17 @@ protected: constexpr static bool value = true; }; + //! \brief Predicate for detecting variants. + template + struct is_variant { + constexpr static bool value = false; + }; + + template + struct is_variant> { + constexpr static bool value = true; + }; + //! \brief Predicate for smart pointers. template struct is_ptr {