oxen-core/src/serialization/boost_std_variant.h
Jason Rhinelander b7dd5e8911 Target macos 10.12
When targetting macos <10.14 macos won't allow use of anything from
C++17 that throws, such as:
- std::get on a variant
- std::visit
- std::optional::value()
- std::any_cast

This avoids all of these.

For std::get, we either replace with std::get_if (where appropriate), or
else use a `var::get` implementation of std::get added to lokimq (also
updated here).  (This `var` namespace is just an `std` alias everywhere
*except* old target macos).

For std::visit, likewise lokimq adds an var::visit implementation for
old macos that we use.

std::optional::value() uses weren't useful anyway as everywhere it calls
them we've already checked that the option has a value, in which case we
can use `*opt` (which doesn't check for contents and throw).

std::any just has to be avoided as far as I can tell, but the one place
we used it is only ever a block, so I just replaced it with a `const
block*`.
2020-10-18 11:18:08 -03:00

52 lines
1.8 KiB
C++

#pragma once
// Adapts boost::serialization to support std::variant, serializing just as a boost::variant would
// be serialized (so that the serialized boost::variant<T...> and std::variant<T...> values are
// interchangeable).
//
#include <lokimq/variant.h>
#include <boost/archive/archive_exception.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
namespace boost::serialization {
template <class Archive, typename... T>
void save(Archive& ar, std::variant<T...> const& v, unsigned int /*version*/) {
int index = static_cast<int>(v.index());
ar << boost::serialization::make_nvp("which", index);
var::visit([&ar](const auto& v) { ar << boost::serialization::make_nvp("value", v); }, v);
}
template <class Archive, typename Variant, typename T, typename... More>
void load_variant_impl(Archive& ar, int index, Variant& v) {
if (index == 0) {
T value;
ar >> boost::serialization::make_nvp("value", value);
v = value;
ar.reset_object_address(&var::get<T>(v), &value);
}
else if constexpr (sizeof...(More) > 0) {
return load_variant_impl<Archive, Variant, More...>(ar, index - 1, v);
}
}
template <class Archive, typename... T>
void load(Archive & ar, std::variant<T...>& v, const unsigned int version) {
int index;
ar >> boost::serialization::make_nvp("which", index);
if (index < 0 || index >= (int) sizeof...(T))
throw boost::archive::archive_exception{boost::archive::archive_exception::unsupported_version};
load_variant_impl<Archive, std::variant<T...>, T...>(ar, index, v);
}
template <class Archive, typename... T>
inline void serialize(Archive& ar, std::variant<T...>& v, const unsigned int file_version) {
split_free(ar,v,file_version);
}
} // namespace boost::serialization