Line data Source code
1 : /*! \file variant.hpp
2 : \brief Support for std::variant
3 : \ingroup STLSupport */
4 : /*
5 : Copyright (c) 2014, 2017, Randolph Voorhies, Shane Grant, Juan Pedro
6 : Bolivar Puente. All rights reserved.
7 :
8 : Redistribution and use in source and binary forms, with or without
9 : modification, are permitted provided that the following conditions are met:
10 : * Redistributions of source code must retain the above copyright
11 : notice, this list of conditions and the following disclaimer.
12 : * Redistributions in binary form must reproduce the above copyright
13 : notice, this list of conditions and the following disclaimer in the
14 : documentation and/or other materials provided with the distribution.
15 : * Neither the name of the copyright holder nor the
16 : names of its contributors may be used to endorse or promote products
17 : derived from this software without specific prior written permission.
18 :
19 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 : ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 : WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
23 : DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 : ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : */
30 : #ifndef CEREAL_TYPES_STD_VARIANT_HPP_
31 : #define CEREAL_TYPES_STD_VARIANT_HPP_
32 :
33 : #include "cereal/cereal.hpp"
34 : #include <variant>
35 : #include <cstdint>
36 :
37 : namespace cereal
38 : {
39 : namespace variant_detail
40 : {
41 : //! @internal
42 : template <class Archive>
43 : struct variant_save_visitor
44 : {
45 12 : variant_save_visitor(Archive & ar_) : ar(ar_) {}
46 :
47 : template<class T>
48 12 : void operator()(T const & value) const
49 : {
50 12 : ar( CEREAL_NVP_("data", value) );
51 12 : }
52 :
53 : Archive & ar;
54 : };
55 :
56 : //! @internal
57 : template<int N, class Variant, class Archive>
58 : typename std::enable_if<N == std::variant_size_v<Variant>, void>::type
59 0 : load_variant(Archive & /*ar*/, int /*target*/, Variant & /*variant*/)
60 : {
61 0 : throw ::cereal::Exception("Error traversing variant during load");
62 : }
63 : //! @internal
64 : template<int N, class Variant, class Archive>
65 : typename std::enable_if<N < std::variant_size_v<Variant>, void>::type
66 24 : load_variant(Archive & ar, int target, Variant & variant)
67 : {
68 24 : if(N == target)
69 : {
70 12 : variant.template emplace<N>();
71 12 : ar( CEREAL_NVP_("data", std::get<N>(variant)) );
72 : }
73 : else
74 12 : load_variant<N+1>(ar, target, variant);
75 24 : }
76 :
77 : } // namespace variant_detail
78 :
79 : //! Saving for std::variant
80 : template <class Archive, typename VariantType1, typename... VariantTypes> inline
81 12 : void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::variant<VariantType1, VariantTypes...> const & variant )
82 : {
83 12 : std::int32_t index = static_cast<std::int32_t>(variant.index());
84 12 : ar( CEREAL_NVP_("index", index) );
85 12 : variant_detail::variant_save_visitor<Archive> visitor(ar);
86 12 : std::visit(visitor, variant);
87 12 : }
88 :
89 : //! Loading for std::variant
90 : template <class Archive, typename... VariantTypes> inline
91 12 : void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::variant<VariantTypes...> & variant )
92 : {
93 : using variant_t = typename std::variant<VariantTypes...>;
94 :
95 : std::int32_t index;
96 12 : ar( CEREAL_NVP_("index", index) );
97 12 : if(index >= static_cast<std::int32_t>(std::variant_size_v<variant_t>))
98 0 : throw Exception("Invalid 'index' selector when deserializing std::variant");
99 :
100 12 : variant_detail::load_variant<0>(ar, index, variant);
101 12 : }
102 :
103 : //! Serializing a std::monostate
104 : template <class Archive>
105 : void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, std::monostate const & ) {}
106 : } // namespace cereal
107 :
108 : #endif // CEREAL_TYPES_STD_VARIANT_HPP_
|