MSVC support for doctest, boost variant serialization

This commit is contained in:
Shane Grant
2019-10-20 17:17:42 -07:00
parent 62034cbe26
commit 33224f4660
2 changed files with 43 additions and 30 deletions

View File

@@ -30,6 +30,13 @@
#ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_
#define CEREAL_TYPES_BOOST_VARIANT_HPP_
//! @internal
#if defined(_MSC_VER) && _MSC_VER < 1911
#define CEREAL_CONSTEXPR_LAMBDA
#else // MSVC 2017 or newer, all other compilers
#define CEREAL_CONSTEXPR_LAMBDA constexpr
#endif
#include "cereal/cereal.hpp"
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/static_visitor.hpp>
@@ -45,65 +52,65 @@ namespace cereal
variant_save_visitor(Archive & ar_) : ar(ar_) {}
template<class T>
void operator()(T const & value) const
{
ar( CEREAL_NVP_("data", value) );
}
void operator()(T const & value) const
{
ar( CEREAL_NVP_("data", value) );
}
Archive & ar;
};
//! @internal
template<class T, class Variant, class Archive>
typename std::enable_if<std::is_default_constructible<T>::value>::type
load_variant(Archive & ar, Variant & variant)
{
T value;
ar( CEREAL_NVP_("data", value) );
variant = std::move(value);
T value;
ar( CEREAL_NVP_("data", value) );
variant = std::move(value);
}
//! @internal
template <class Archive, class T>
struct LoadAndConstructLoadWrapper
{
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
LoadAndConstructLoadWrapper() :
construct( reinterpret_cast<T *>( &st ) )
{ }
LoadAndConstructLoadWrapper() :
construct( reinterpret_cast<T *>( &st ) )
{ }
~LoadAndConstructLoadWrapper()
~LoadAndConstructLoadWrapper()
{
if (construct.itsValid)
{
if (construct.itsValid)
{
construct->~T();
}
construct->~T();
}
}
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
{
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
}
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
{
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
}
ST st;
::cereal::construct<T> construct;
ST st;
::cereal::construct<T> construct;
};
//! @internal
template<class T, class Variant, class Archive>
typename std::enable_if<!std::is_default_constructible<T>::value>::type
load_variant(Archive & ar, Variant & variant)
{
LoadAndConstructLoadWrapper<Archive, T> loadWrapper;
LoadAndConstructLoadWrapper<Archive, T> loadWrapper;
ar( CEREAL_NVP_("data", loadWrapper) );
variant = std::move(*loadWrapper.construct.ptr());
ar( CEREAL_NVP_("data", loadWrapper) );
variant = std::move(*loadWrapper.construct.ptr());
}
} // namespace boost_variant_detail
//! Saving for boost::variant
template <class Archive, typename... VariantTypes> inline
template <class Archive, typename ... VariantTypes> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
{
int32_t which = variant.which();
@@ -113,14 +120,14 @@ namespace cereal
}
//! Loading for boost::variant
template <class Archive, typename... VariantTypes> inline
template <class Archive, typename ... VariantTypes> inline
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
{
int32_t which;
ar( CEREAL_NVP_("which", which) );
using LoadFuncType = void(*)(Archive &, boost::variant<VariantTypes...> &);
constexpr LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant<VariantTypes>...};
CEREAL_CONSTEXPR_LAMBDA LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant<VariantTypes>...};
if(which >= int32_t(sizeof(loadFuncArray)/sizeof(loadFuncArray[0])))
throw Exception("Invalid 'which' selector when deserializing boost::variant");
@@ -129,4 +136,6 @@ namespace cereal
}
} // namespace cereal
#undef CEREAL_CONSTEXPR_LAMBDA
#endif // CEREAL_TYPES_BOOST_VARIANT_HPP_

View File

@@ -302,7 +302,11 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom constr
#define DOCTEST_ALIGNMENT(x)
#define DOCTEST_NORETURN __declspec(noreturn)
#ifndef DOCTEST_THREAD_LOCAL
#if DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)
#define DOCTEST_THREAD_LOCAL /* not supported */
#else
#define DOCTEST_THREAD_LOCAL __declspec(thread)
#endif // MSVC version
#endif // THREAD_LOCAL
#else // MSVC
#define DOCTEST_NOINLINE __attribute__((noinline))