Skip to content

Commit

Permalink
Merge pull request #3156 from STEllAR-GROUP/fix_3134
Browse files Browse the repository at this point in the history
Fixing serialization of classes with incompatible serialize signature
  • Loading branch information
sithhell committed Feb 12, 2018
2 parents 98effdc + 241a985 commit bac5a9d
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 6 deletions.
28 changes: 23 additions & 5 deletions hpx/runtime/serialization/access.hpp
Expand Up @@ -8,19 +8,17 @@
#define HPX_SERIALIZATION_ACCESS_HPP

#include <hpx/runtime/serialization/serialization_fwd.hpp>
#include <hpx/traits/has_member_xxx.hpp>
#include <hpx/traits/polymorphic_traits.hpp>
#include <hpx/util/decay.hpp>

#include <string>
#include <type_traits>
#include <utility>

namespace hpx { namespace serialization
{
namespace detail
{
HPX_HAS_MEMBER_XXX_TRAIT_DEF(serialize);

template <class T> HPX_FORCEINLINE
void serialize_force_adl(output_archive& ar, const T& t, unsigned)
{
Expand All @@ -36,6 +34,26 @@ namespace hpx { namespace serialization

class access
{
template <class T>
class has_serialize
{
template <class T1> static std::false_type test(...);

// the following expression sfinae trick
// appears to work on clang-3.4, gcc-4.9,
// icc-16, msvc-2017 (at least)
// note that this detection would have been much easier
// to implement if there hadn't been an issue with gcc:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82478
template <class T1, class = decltype(
std::declval<typename std::remove_const<T1>::type &>().
serialize(std::declval<output_archive &>(), 0u))>
static std::true_type test(int);

public:
static constexpr bool value = decltype(test<T>(0))::value;
};

template <class T>
class serialize_dispatcher
{
Expand Down Expand Up @@ -73,7 +91,7 @@ namespace hpx { namespace serialization
struct empty
{
template <class Archive>
static void call(Archive& ar, T& t, unsigned)
static void call(Archive&, T&, unsigned)
{
}
};
Expand All @@ -95,7 +113,7 @@ namespace hpx { namespace serialization
hpx::traits::is_intrusive_polymorphic<T>::value,
intrusive_polymorphic,
typename std::conditional<
detail::has_serialize<T>::value,
has_serialize<T>::value,
intrusive_usual,
typename std::conditional<
std::is_empty<T>::value,
Expand Down
2 changes: 1 addition & 1 deletion hpx/util/tuple.hpp
Expand Up @@ -306,7 +306,7 @@ namespace hpx { namespace util
}

template <typename Archive>
void serialize(Archive& ar, unsigned int const version)
void serialize(Archive& ar, unsigned int const)
{
int const _sequencer[] = {
((ar & this->get<Is>()), 0)...
Expand Down
1 change: 1 addition & 0 deletions tests/unit/serialization/CMakeLists.txt
Expand Up @@ -21,6 +21,7 @@ set(tests
serialization_partitioned_vector
serialization_variant
serialize_buffer
serialize_with_incompatible_signature
zero_copy_serialization
)

Expand Down
45 changes: 45 additions & 0 deletions tests/unit/serialization/serialize_with_incompatible_signature.cpp
@@ -0,0 +1,45 @@
// Copyright (c) 2018 Anton Bikineev
//
// Distributed under 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)

#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/util/lightweight_test.hpp>

#include <vector>

struct A
{
double a;
int p;

void serialize(int, unsigned) {
// 3rd-party logic...
}
};

template <class Ar>
void serialize(Ar& ar, A& a, unsigned) {
ar & a.a;
ar & a.p;
}

int main()
{
std::vector<char> vector;
{
hpx::serialization::output_archive oar(vector);
A a{2., 4};
oar << a;
}

{
A a;
hpx::serialization::input_archive iar(vector);
iar >> a;
HPX_TEST_EQ(a.a, 2.);
HPX_TEST_EQ(a.p, 4);
}

return 0;
}

0 comments on commit bac5a9d

Please sign in to comment.