Reputation: 13952
Considering the following example of serialization, how does boost cope with saving data when this data is const and the serialization function is not a const function ?
Is there a const cast somewhere ?
struct Settings
{
Settings();
uint32_t buffers_size;
uint32_t messages;
};
template < class Archive >
void serialize(Archive& ar, Settings& settings, unsigned int /*version*/)
{
using boost::serialization::make_nvp;
ar
& make_nvp< uint32_t >("buffers_size", settings.buffers_size )
& make_nvp< uint32_t >("messages", settings.messages);
}
Upvotes: 2
Views: 1310
Reputation: 82171
As far as I can tell, the constness is indeed casted away before saving the object. I think the relevant code is in oserializer.hpp
:
template<class Archive, class T>
BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
basic_oarchive & ar,
const void *x
) const {
// make sure call is routed through the highest interface that might
// be specialized by the user.
BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
boost::serialization::serialize_adl(
boost::serialization::smart_cast_reference<Archive &>(ar),
* static_cast<T *>(const_cast<void *>(x)),
version()
);
}
Before this method is called, the serialized object reference is turned into a const void *
, corresponding to the second parameter here. The constness of this pointer is casted away, and the resulting pointer is casted to the appropriate pointer type, which is then dereferenced.
This raises the question of the possibility of invoking undefined behavior when trying to serialize a const
object: if the serialize
member/free function somehow modifies the object, then creating a const
object and saving it to an archive would be undefined behavior, and go unnoticed at compile-time!
If you split the function into save
and load
, then you must mark save
as const
, which prevents you from accidentally modifying the object.
Upvotes: 2