Open
Description
Ran into cereal assertion error when trying to use external split load/save functions with explicit version on a subclass which has two constructors, a default constructor and a non-default one.
The non-default constructor seems to have somehow caused some interesting issues. When I did any one of these, the code compiles all okay:
- comment out the non-default constructor
- Make the non-default constructor explicit like this:
explicit Derived(const std::string& name) ...
- remove the explicit version
- use serialize() instead of load/save.
If I missed something from the doc, please point out. (the doc just said "cereal requires access to a default constructor for types it serializes", in my case, there is a public default constructor.)
Here's the code to produce this issue:
#include <string>
#include <sstream>
#include <memory>
#include <cassert>
#include <cereal/cereal.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/polymorphic.hpp>
struct Base
{
virtual ~Base() = default;
int id = 0;
};
struct Derived: public Base
{
Derived() = default;
Derived(const std::string& name): name(name){}
virtual ~Derived() = default;
std::string name;
};
namespace cereal{
template<class Archive>
void save(Archive& ar, const Base& obj, const std::uint32_t version)
{
ar(obj.id);
}
template<class Archive>
void load(Archive& ar, Base& obj, const std::uint32_t version)
{
ar(obj.id);
}
template<class Archive>
void save(Archive& ar, const Derived& obj, const std::uint32_t version)
{
ar(base_class<Base>(&obj), obj.name);
}
template<class Archive>
void load(Archive& ar, Derived& obj, const std::uint32_t version)
{
ar(base_class<Base>(&obj), obj.name);
}
}
CEREAL_REGISTER_TYPE(Derived)
int main(int argc, char* argv[])
{
using namespace cereal;
std::ostringstream osm;
BinaryOutputArchive oarc(osm);
std::shared_ptr<Derived> obj = std::make_shared<Derived>();
obj->id = 10;
obj->name = "test name";
oarc(std::dynamic_pointer_cast<Base>(obj));
std::istringstream ism(osm.str());
BinaryInputArchive iarc(ism);
std::shared_ptr<Base> obj2;
iarc(obj2);
auto actual = std::dynamic_pointer_cast<Derived>(obj2);
assert(obj->name == actual->name);
return 0;
}
Here's the compile error:
cereal/include/cereal/cereal.hpp: In instantiation of ‘ArchiveType& cereal::OutputArchive<ArchiveType, Flags>::processImpl(const T&) [with T = std::basic_string<char>; typename cereal::traits::detail::EnableIfHelper<(cereal::traits::has_invalid_output_versioning<T, ArchiveType>::value || ((! cereal::traits::is_output_serializable<T, ArchiveType>::value) && ((!(Flags & AllowEmptyClassElision)) || ((Flags & AllowEmptyClassElision) && (! std::is_empty<T>::value)))))>::type <anonymous> = (cereal::traits::detail::type)0; ArchiveType = cereal::BinaryOutputArchive; unsigned int Flags = 1u]’:
cereal/include/cereal/cereal.hpp:347:9: required from ‘void cereal::OutputArchive<ArchiveType, Flags>::process(T&&) [with T = std::basic_string<char>&; ArchiveType = cereal::BinaryOutputArchive; unsigned int Flags = 1u]’
cereal/include/cereal/cereal.hpp:249:9: required from ‘ArchiveType& cereal::OutputArchive<ArchiveType, Flags>::operator()(Types&& ...) [with Types = {std::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; ArchiveType = cereal::BinaryOutputArchive; unsigned int Flags = 1u]’
cereal/include/cereal/details/polymorphic_impl.hpp:545:59: required from ‘static void cereal::detail::OutputBindingCreator<Archive, T>::writeMetadata(Archive&) [with Archive = cereal::BinaryOutputArchive; T = Derived]’
cereal/include/cereal/details/polymorphic_impl.hpp:621:29: required from ‘cereal::detail::OutputBindingCreator<Archive, T>::OutputBindingCreator() [with Archive = cereal::BinaryOutputArchive; T = Derived]::__lambda10’
cereal/include/cereal/details/polymorphic_impl.hpp:618:13: required from ‘struct cereal::detail::OutputBindingCreator<Archive, T>::OutputBindingCreator() [with Archive = cereal::BinaryOutputArchive; T = Derived]::__lambda10’
cereal/include/cereal/details/polymorphic_impl.hpp:617:32: [ skipping 4 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
cereal/include/cereal/details/polymorphic_impl.hpp:706:96: required from ‘static void cereal::detail::polymorphic_serialization_support<Archive, T>::instantiate() [with Archive = cereal::BinaryOutputArchive; T = Derived]’
cereal/include/cereal/details/polymorphic_impl.hpp:686:5: required from ‘struct cereal::detail::polymorphic_serialization_support<cereal::BinaryOutputArchive, Derived>’
cereal/include/cereal/archives/binary.hpp:163:1: required by substitution of ‘template<class T, class BindingTag> typename cereal::detail::polymorphic_serialization_support<cereal::BinaryOutputArchive, T>::type cereal::detail::instantiate_polymorphic_binding(T*, cereal::BinaryOutputArchive*, BindingTag, cereal::detail::adl_tag) [with T = Derived; BindingTag = cereal::detail::{anonymous}::polymorphic_binding_tag]’
cereal/include/cereal/details/polymorphic_impl.hpp:724:86: required from ‘void cereal::detail::bind_to_archives<T, Tag>::bind(std::false_type) const [with T = Derived; Tag = cereal::detail::{anonymous}::polymorphic_binding_tag; std::false_type = std::integral_constant<bool, false>]’
cereal/include/cereal/details/polymorphic_impl.hpp:738:37: required from ‘const cereal::detail::bind_to_archives<T, Tag>& cereal::detail::bind_to_archives<T, Tag>::bind() const [with T = Derived; Tag = cereal::detail::{anonymous}::polymorphic_binding_tag]’
simplecerealtest.cpp:53:1: required from here
cereal/include/cereal/cereal.hpp:472:9: error: static assertion failed: cereal found more than one compatible output serialization function for the provided type and archive combination.
Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these).
Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions.
Note that serialization functions can be inherited which may lead to the aforementioned ambiguities.
In addition, you may not mix versioned with non-versioned serialization functions.
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
cereal version used is release 1.2.2
Compiler used:
$ c++ --version
c++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Metadata
Metadata
Assignees
Labels
No labels