Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:12

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_VARIANT_PROXY_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_VARIANT_PROXY_HPP
0009 
0010 #include <boost/core/nvp.hpp>
0011 #include <boost/histogram/axis/traits.hpp> // variant_access
0012 #include <boost/histogram/detail/static_if.hpp>
0013 #include <boost/mp11/algorithm.hpp> // mp_with_index, mp_find, mp_at
0014 #include <boost/mp11/list.hpp>      // mp_size
0015 #include <boost/throw_exception.hpp>
0016 #include <stdexcept>
0017 
0018 namespace boost {
0019 namespace histogram {
0020 namespace detail {
0021 
0022 // This is a workaround to remain backward compatible in the serialization format. The
0023 // proxy uses only the public interface of axis::variant for serialization and works
0024 // independently of the underlying variant implementation.
0025 template <class Variant>
0026 struct variant_proxy {
0027   Variant& variant;
0028 
0029   template <class Archive>
0030   void serialize(Archive& ar, unsigned /* version */) {
0031     detail::static_if_c<Archive::is_loading::value>(
0032         [this](auto& ar) { // loading
0033           int which = 0;
0034           ar >> make_nvp("which", which);
0035           constexpr unsigned N = mp11::mp_size<Variant>::value;
0036           if (which < 0 || static_cast<unsigned>(which) >= N)
0037             // throw if which >= N, can happen if type was removed from variant
0038             BOOST_THROW_EXCEPTION(
0039                 std::runtime_error("variant has fewer types than stored version"));
0040           mp11::mp_with_index<N>(static_cast<unsigned>(which), [&ar, this](auto i) {
0041             using T = mp11::mp_at_c<Variant, i>;
0042             T value;
0043             ar >> make_nvp("value", value);
0044             this->variant = std::move(value);
0045             T* new_address = variant_access::template get_if<T>(&this->variant);
0046             ar.reset_object_address(new_address, &value);
0047           });
0048         },
0049         [this](auto& ar) { // saving
0050           visit(
0051               [&ar](const auto& value) {
0052                 using T = std::decay_t<decltype(value)>;
0053                 const int which = static_cast<int>(mp11::mp_find<Variant, T>::value);
0054                 ar << make_nvp("which", which);
0055                 ar << make_nvp("value", value);
0056               },
0057               this->variant);
0058         },
0059         ar);
0060   }
0061 };
0062 
0063 } // namespace detail
0064 } // namespace histogram
0065 } // namespace boost
0066 
0067 #endif