mirror of
https://github.com/boostorg/serialization.git
synced 2026-01-19 04:42:10 +00:00
Merge pull request #148 from sdebionne/add-std-variant-support
Add support for C++17 std::variant
This commit is contained in:
@@ -335,6 +335,7 @@ archive_test(test_unregistered)
|
||||
archive_test(test_unique_ptr)
|
||||
archive_test(test_valarray)
|
||||
archive_test(test_variant A)
|
||||
archive_test(test_std_variant A)
|
||||
archive_test(test_vector A)
|
||||
|
||||
polymorphic_archive_test(test_dll_exported polymorphic_derived1)
|
||||
|
||||
@@ -919,6 +919,7 @@ As of this writing, the library contains serialization of the following boost cl
|
||||
<li>shared_ptr
|
||||
<li>auto_ptr (demo)
|
||||
</ul>
|
||||
C++17 <code style="white-space: normal">std::variant is supported as well</code>.
|
||||
Others are being added to the list so check the boost files section and headers for
|
||||
new implementations!
|
||||
<hr>
|
||||
|
||||
204
include/boost/serialization/std_variant.hpp
Normal file
204
include/boost/serialization/std_variant.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#ifndef BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
#define BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// variant.hpp - non-intrusive serialization of variant types
|
||||
//
|
||||
// copyright (c) 2019 Samuel Debionne, ESRF
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
//
|
||||
// Widely inspired form boost::variant serialization
|
||||
//
|
||||
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_save_visitor
|
||||
{
|
||||
std_variant_save_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
m_ar << BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_load_visitor
|
||||
{
|
||||
std_variant_load_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T & value) const
|
||||
{
|
||||
m_ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
template<class Archive, class ...Types>
|
||||
void save(
|
||||
Archive & ar,
|
||||
std::variant<Types...> const & v,
|
||||
unsigned int /*version*/
|
||||
){
|
||||
const std::size_t which = v.index();
|
||||
ar << BOOST_SERIALIZATION_NVP(which);
|
||||
std_variant_save_visitor<Archive> visitor(ar);
|
||||
std::visit(visitor, v);
|
||||
}
|
||||
|
||||
// Minimalist metaprogramming for handling parameter pack
|
||||
namespace mp {
|
||||
namespace detail {
|
||||
template <typename Seq>
|
||||
struct front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct front_impl<Seq<T, Ts...>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename Seq>
|
||||
struct pop_front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct pop_front_impl<Seq<T, Ts...>> {
|
||||
using type = Seq<Ts...>;
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
template <typename... Ts>
|
||||
struct typelist {};
|
||||
|
||||
template <typename Seq>
|
||||
using front = typename detail::front_impl<Seq>::type;
|
||||
|
||||
template <typename Seq>
|
||||
using pop_front = typename detail::pop_front_impl<Seq>::type;
|
||||
} // namespace mp
|
||||
|
||||
template<std::size_t N, class Seq>
|
||||
struct variant_impl
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & ar,
|
||||
std::size_t which,
|
||||
V & v,
|
||||
const unsigned int version
|
||||
){
|
||||
if(which == 0){
|
||||
// note: A non-intrusive implementation (such as this one)
|
||||
// necessary has to copy the value. This wouldn't be necessary
|
||||
// with an implementation that de-serialized to the address of the
|
||||
// aligned storage included in the variant.
|
||||
using type = mp::front<Seq>;
|
||||
type value;
|
||||
ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
v = std::move(value);
|
||||
type * new_address = & std::get<type>(v);
|
||||
ar.reset_object_address(new_address, & value);
|
||||
return;
|
||||
}
|
||||
//typedef typename mpl::pop_front<S>::type type;
|
||||
using types = mp::pop_front<Seq>;
|
||||
variant_impl<N - 1, types>::load(ar, which - 1, v, version);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Seq>
|
||||
struct variant_impl<0, Seq>
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & /*ar*/,
|
||||
std::size_t /*which*/,
|
||||
V & /*v*/,
|
||||
const unsigned int /*version*/
|
||||
){}
|
||||
};
|
||||
|
||||
template<class Archive, class... Types>
|
||||
void load(
|
||||
Archive & ar,
|
||||
std::variant<Types...>& v,
|
||||
const unsigned int version
|
||||
){
|
||||
std::size_t which;
|
||||
ar >> BOOST_SERIALIZATION_NVP(which);
|
||||
if(which >= sizeof...(Types))
|
||||
// this might happen if a type was removed from the list of variant types
|
||||
boost::serialization::throw_exception(
|
||||
boost::archive::archive_exception(
|
||||
boost::archive::archive_exception::unsupported_version
|
||||
)
|
||||
);
|
||||
variant_impl<sizeof...(Types), mp::typelist<Types...>>::load(ar, which, v, version);
|
||||
}
|
||||
|
||||
template<class Archive,class... Types>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::variant<Types...> & v,
|
||||
const unsigned int file_version
|
||||
){
|
||||
split_free(ar,v,file_version);
|
||||
}
|
||||
|
||||
// Specialization for std::monostate
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar, std::monostate &, const unsigned int /*version*/)
|
||||
{}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
|
||||
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class... Types>
|
||||
struct tracking_level<
|
||||
std::variant<Types...>
|
||||
>{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_< ::boost::serialization::track_always> type;
|
||||
BOOST_STATIC_CONSTANT(int, value = type::value);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_SERIALIZATION_VARIANT_HPP
|
||||
176
include/boost/serialization/variant2.hpp
Normal file
176
include/boost/serialization/variant2.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#ifndef BOOST_SERIALIZATION_VARIANT2_HPP
|
||||
#define BOOST_SERIALIZATION_VARIANT2_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// variant.hpp - non-intrusive serialization of variant types
|
||||
//
|
||||
// copyright (c) 2019 Samuel Debionne, ESRF
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
//
|
||||
// Widely inspired form boost::variant serialization
|
||||
//
|
||||
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
#include <boost/mp11/list.hpp>
|
||||
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive>
|
||||
struct variant2_save_visitor
|
||||
{
|
||||
variant2_save_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
m_ar << BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
|
||||
template<class Archive>
|
||||
struct variant2_load_visitor
|
||||
{
|
||||
variant2_load_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T & value) const
|
||||
{
|
||||
m_ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
template<class Archive, class ...Types>
|
||||
void save(
|
||||
Archive & ar,
|
||||
variant2::variant<Types...> const & v,
|
||||
unsigned int /*version*/
|
||||
){
|
||||
const std::size_t which = v.index();
|
||||
ar << BOOST_SERIALIZATION_NVP(which);
|
||||
variant2_save_visitor<Archive> visitor(ar);
|
||||
std::visit(visitor, v);
|
||||
}
|
||||
|
||||
template<std::size_t N, class Seq>
|
||||
struct variant_impl
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & ar,
|
||||
std::size_t which,
|
||||
V & v,
|
||||
const unsigned int version
|
||||
){
|
||||
if(which == 0){
|
||||
// note: A non-intrusive implementation (such as this one)
|
||||
// necessary has to copy the value. This wouldn't be necessary
|
||||
// with an implementation that de-serialized to the address of the
|
||||
// aligned storage included in the variant.
|
||||
using type = mp11::mp_front<Seq>;
|
||||
type value;
|
||||
ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
v = std::move(value);
|
||||
type * new_address = & variant2::get<type>(v);
|
||||
ar.reset_object_address(new_address, & value);
|
||||
return;
|
||||
}
|
||||
//typedef typename mpl::pop_front<S>::type type;
|
||||
using types = mp11::mp_pop_front<Seq>;
|
||||
variant_impl<N - 1, types>::load(ar, which - 1, v, version);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Seq>
|
||||
struct variant_impl<0, Seq>
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & /*ar*/,
|
||||
std::size_t /*which*/,
|
||||
V & /*v*/,
|
||||
const unsigned int /*version*/
|
||||
){}
|
||||
};
|
||||
|
||||
template<class Archive, class... Types>
|
||||
void load(
|
||||
Archive & ar,
|
||||
variant2::variant<Types...> & v,
|
||||
const unsigned int version
|
||||
){
|
||||
std::size_t which;
|
||||
ar >> BOOST_SERIALIZATION_NVP(which);
|
||||
if(which >= sizeof...(Types))
|
||||
// this might happen if a type was removed from the list of variant types
|
||||
boost::serialization::throw_exception(
|
||||
boost::archive::archive_exception(
|
||||
boost::archive::archive_exception::unsupported_version
|
||||
)
|
||||
);
|
||||
variant_impl<sizeof...(Types), mp11::mp_list<Types...>>::load(ar, which, v, version);
|
||||
}
|
||||
|
||||
template<class Archive,class... Types>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
variant2::variant<Types...> & v,
|
||||
const unsigned int file_version
|
||||
){
|
||||
split_free(ar,v,file_version);
|
||||
}
|
||||
|
||||
// Specialization for std::monostate
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar, variant2::monostate &, const unsigned int /*version*/)
|
||||
{}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
|
||||
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class... Types>
|
||||
struct tracking_level<
|
||||
variant2::variant<Types...>
|
||||
>{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_< ::boost::serialization::track_always> type;
|
||||
BOOST_STATIC_CONSTANT(int, value = type::value);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_SERIALIZATION_VARIANT2_HPP
|
||||
@@ -112,6 +112,7 @@ test-suite "serialization" :
|
||||
[ test-bsl-run_files test_unique_ptr ]
|
||||
[ test-bsl-run_files test_valarray ]
|
||||
[ test-bsl-run_files test_variant : A ]
|
||||
[ test-bsl-run_files test_std_variant : A : : [ requires cxx17_hdr_variant ] ] # BOOST_NO_CXX17_HDR_VARIANT
|
||||
[ test-bsl-run_files test_vector : A ]
|
||||
[ test-bsl-run_files test_shared_ptr ]
|
||||
[ test-bsl-run_files test_shared_ptr_multi_base ]
|
||||
@@ -188,4 +189,3 @@ if ! $(BOOST_ARCHIVE_LIST) {
|
||||
[ compile test_const_pass.cpp ]
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
256
test/test_std_variant.cpp
Normal file
256
test/test_std_variant.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// test_variant.cpp
|
||||
// test of non-intrusive serialization of variant types
|
||||
//
|
||||
// copyright (c) 2005
|
||||
// troy d. straszheim <troy@resophonic.com>
|
||||
// http://www.resophonic.com
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
//
|
||||
// thanks to Robert Ramey and Peter Dimov.
|
||||
//
|
||||
|
||||
#include <cstddef> // NULL
|
||||
#include <cstdio> // remove
|
||||
#include <fstream>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/math/special_functions/next.hpp> // float_distance
|
||||
#if defined(BOOST_NO_STDC_NAMESPACE)
|
||||
namespace std{
|
||||
using ::remove;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1020)
|
||||
# pragma warning (disable : 4786) // too long name, harmless warning
|
||||
#endif
|
||||
|
||||
#include "test_tools.hpp"
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/serialization/std_variant.hpp>
|
||||
|
||||
#include "A.hpp"
|
||||
#include "A.ipp"
|
||||
|
||||
|
||||
template <class T>
|
||||
void test_type(const T& gets_written){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(testfile != NULL);
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
||||
oa << boost::serialization::make_nvp("written", gets_written);
|
||||
}
|
||||
|
||||
T got_read;
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
||||
ia >> boost::serialization::make_nvp("written", got_read);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(gets_written, got_read);
|
||||
|
||||
std::remove(testfile);
|
||||
}
|
||||
|
||||
// this verifies that if you try to read in a variant from a file
|
||||
// whose "which" is illegal for the one in memory (that is, you're
|
||||
// reading in to a different variant than you wrote out to) the load()
|
||||
// operation will throw. One could concievably add checking for
|
||||
// sequence length as well, but this would add size to the archive for
|
||||
// dubious benefit.
|
||||
//
|
||||
void do_bad_read()
|
||||
{
|
||||
std::variant<bool, float, int, std::string> big_variant;
|
||||
big_variant = std::string("adrenochrome");
|
||||
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(testfile != NULL);
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
||||
oa << BOOST_SERIALIZATION_NVP(big_variant);
|
||||
}
|
||||
std::variant<bool, float, int> little_variant;
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
||||
bool exception_invoked = false;
|
||||
BOOST_TRY {
|
||||
ia >> BOOST_SERIALIZATION_NVP(little_variant);
|
||||
} BOOST_CATCH (boost::archive::archive_exception const& e) {
|
||||
BOOST_CHECK(boost::archive::archive_exception::unsupported_version == e.code);
|
||||
exception_invoked = true;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
BOOST_CHECK(exception_invoked);
|
||||
}
|
||||
}
|
||||
|
||||
struct H {
|
||||
int i;
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive &ar, H & h, const unsigned int /*file_version*/){
|
||||
ar & boost::serialization::make_nvp("h", h.i);
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
inline bool operator==(H const & lhs, H const & rhs) {
|
||||
return lhs.i == rhs.i;
|
||||
}
|
||||
|
||||
inline bool operator!=(H const & lhs, H const & rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator<(H const & lhs, H const & rhs) {
|
||||
return lhs.i < rhs.i;
|
||||
}
|
||||
|
||||
inline std::size_t hash_value(H const & val) {
|
||||
return val.i;
|
||||
}
|
||||
|
||||
void test_pointer(){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(testfile != NULL);
|
||||
typedef std::variant<H, int> variant_t;
|
||||
H const h = {5};
|
||||
variant_t v(h);
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
||||
oa << boost::serialization::make_nvp("written", v);
|
||||
const H * h_ptr = & std::get<H>(v);
|
||||
oa << boost::serialization::make_nvp("written", h_ptr);
|
||||
}
|
||||
variant_t v2;
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
||||
ia >> boost::serialization::make_nvp("written", v2);
|
||||
H * h2_ptr;
|
||||
ia >> boost::serialization::make_nvp("written", h2_ptr);
|
||||
BOOST_CHECK_EQUAL(h, std::get<H>(v2));
|
||||
BOOST_CHECK_EQUAL(h2_ptr, & std::get<H>(v2));
|
||||
}
|
||||
BOOST_CHECK_EQUAL(v, v2);
|
||||
}
|
||||
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/set.hpp>
|
||||
|
||||
// test a pointer to an object contained into a variant that is an
|
||||
// element of a set
|
||||
void test_variant_set()
|
||||
{
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(testfile != NULL);
|
||||
typedef std::variant<H, int> variant_t;
|
||||
typedef std::set<variant_t> uset_t;
|
||||
uset_t set;
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
||||
H const h = {5};
|
||||
variant_t v(h);
|
||||
set.insert(v);
|
||||
oa << boost::serialization::make_nvp("written", set);
|
||||
H const * const h_ptr = & std::get<H>(*set.begin());
|
||||
oa << boost::serialization::make_nvp("written", h_ptr);
|
||||
}
|
||||
uset_t set2;
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
||||
ia >> boost::serialization::make_nvp("written", set2);
|
||||
H * h_ptr;
|
||||
ia >> boost::serialization::make_nvp("written", h_ptr);
|
||||
const H * h_ptr2 = & std::get<H>(*set2.begin());
|
||||
BOOST_CHECK_EQUAL(h_ptr, h_ptr2);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(set, set2);
|
||||
}
|
||||
|
||||
// test a pointer to an object contained into a variant that is an
|
||||
// element of a map
|
||||
void test_variant_map()
|
||||
{
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(testfile != NULL);
|
||||
typedef std::variant<H, int> variant_t;
|
||||
typedef std::map<int, variant_t> map_t;
|
||||
map_t map;
|
||||
{
|
||||
test_ostream os(testfile, TEST_STREAM_FLAGS);
|
||||
test_oarchive oa(os, TEST_ARCHIVE_FLAGS);
|
||||
H const h = {5};
|
||||
variant_t v(h);
|
||||
map[0] = v;
|
||||
BOOST_ASSERT(1 == map.size());
|
||||
oa << boost::serialization::make_nvp("written", map);
|
||||
H const * const h_ptr = std::get_if<H>(&map[0]);
|
||||
BOOST_CHECK_EQUAL(h_ptr, std::get_if<H>(&map[0]));
|
||||
oa << boost::serialization::make_nvp("written", h_ptr);
|
||||
}
|
||||
map_t map2;
|
||||
{
|
||||
test_istream is(testfile, TEST_STREAM_FLAGS);
|
||||
test_iarchive ia(is, TEST_ARCHIVE_FLAGS);
|
||||
ia >> boost::serialization::make_nvp("written", map2);
|
||||
BOOST_ASSERT(1 == map2.size());
|
||||
H * h_ptr;
|
||||
ia >> boost::serialization::make_nvp("written", h_ptr);
|
||||
H const * const h_ptr2 = std::get_if<H>(&map2[0]);
|
||||
BOOST_CHECK_EQUAL(h_ptr, h_ptr2);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(map, map2);
|
||||
}
|
||||
|
||||
int test_main( int /* argc */, char* /* argv */[] )
|
||||
{
|
||||
{
|
||||
std::variant<bool, int, float, double, A, std::string> v;
|
||||
v = false;
|
||||
test_type(v);
|
||||
v = 1;
|
||||
test_type(v);
|
||||
v = (float) 2.3;
|
||||
test_type(v);
|
||||
v = (double) 6.4;
|
||||
test_type(v);
|
||||
v = std::string("we can't stop here, this is Bat Country");
|
||||
test_type(v);
|
||||
v = A();
|
||||
test_type(v);
|
||||
}
|
||||
test_pointer();
|
||||
test_variant_set();
|
||||
test_variant_map();
|
||||
do_bad_read();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// EOF
|
||||
Reference in New Issue
Block a user