Как можно использовать boost :: serialization с std :: shared_ptr из C ++ 11?

Я знаю, что существует модуль Boost для сериализации из boost :: shared_ptr , но я не могу найти что угодно для std :: shared_ptr .

Кроме того, я не знаю, как это легко реализовать. Боюсь, что следующий код

namespace boost{namespace serialization{
template
inline void serialize(Archive & ar, std::shared_ptr &t, const unsigned int version)
{
  if(Archive::is_loading::value) {T*r;ar>>r;t=r;}
  else {ar<

не работает. В самом деле, если на какой-то объект ссылались несколько раз, он будет загружен с первым запуском ar >> r , а после этого будет скопирован только указатель. Однако мы могли бы создать несколько объектов shared_ptr , указывающих на него, и поэтому уничтожили бы его более одного раза.

Есть идеи по этому поводу?

Некоторые технические подробности о системе, которую я использую:

  • ОС: Ubuntu 11.10 (x64)
  • Компилятор: g ++ (Ubuntu / Linaro 4.6.1-9ubuntu3) 4.6. 1
  • boost версия: 1.46.1 (устанавливается с sudo apt-get install libboost-dev )

24
задан Null 4 April 2016 в 20:43
поделиться

2 ответа

Начиная с Boost 1.56, библиотека сериализации имеет встроенную поддержку для std :: shared_ptr. Вам не нужно реализовывать свои собственные вспомогательные функции сериализации, если вы можете использовать более новую версию библиотеки.

13
ответ дан 28 November 2019 в 23:51
поделиться

Это результат прокрутки собственного на основе заголовка общего указателя повышения, например, на основании <boost/serialization/shared_ptr.hpp>.

Просто скопируйте & amp; Вставьте ниже в заголовочный файл и включите его:

#ifndef BOOST_SERIALIZATION_STD_SHARED_PTR_HPP
#define BOOST_SERIALIZATION_STD_SHARED_PTR_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// shared_ptr.hpp: serialization for boost shared pointer

// (C) Copyright 2004 Robert Ramey and Martin Ecker
// 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.

#include <cstddef> // NULL

#include <boost/config.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/integral_c_tag.hpp>

#include <boost/detail/workaround.hpp>
#include <memory>

#include <boost/serialization/split_free.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/tracking.hpp>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// shared_ptr serialization traits
// version 1 to distinguish from boost 1.32 version. Note: we can only do this
// for a template when the compiler supports partial template specialization

#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
    namespace boost {
    namespace serialization{
        template<class T>
        struct version< ::std::shared_ptr< T > > {
            typedef mpl::integral_c_tag tag;
            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
            typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type;
            #else
            typedef mpl::int_<1> type;
            #endif
            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
            BOOST_STATIC_CONSTANT(int, value = 1);
            #else
            BOOST_STATIC_CONSTANT(int, value = type::value);
            #endif
        };
        // don't track shared pointers
        template<class T>
        struct tracking_level< ::std::shared_ptr< T > > {
            typedef mpl::integral_c_tag tag;
            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
            typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
            #else
            typedef mpl::int_< ::boost::serialization::track_never> type;
            #endif
            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
            BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
            #else
            BOOST_STATIC_CONSTANT(int, value = type::value);
            #endif
        };
    }}
    #define BOOST_SERIALIZATION_SHARED_PTR(T)
#else
    // define macro to let users of these compilers do this
    #define BOOST_SERIALIZATION_SHARED_PTR(T)                         \
    BOOST_CLASS_VERSION(                                              \
        ::std::shared_ptr< T >,                                     \
        1                                                             \
    )                                                                 \
    BOOST_CLASS_TRACKING(                                             \
        ::std::shared_ptr< T >,                                     \
        ::boost::serialization::track_never                           \
    )                                                                 \
    /**/
#endif

namespace boost {
namespace serialization{

#ifndef BOOST_SERIALIZATION_SHARED_PTR_HPP
struct null_deleter {
    void operator()(void const *) const {}
};
#endif

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// serialization for shared_ptr

template<class Archive, class T>
inline void save(
    Archive & ar,
    const std::shared_ptr< T > &t,
    const unsigned int /* file_version */
){
    // The most common cause of trapping here would be serializing
    // something like shared_ptr<int>.  This occurs because int
    // is never tracked by default.  Wrap int in a trackable type
    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
    const T * t_ptr = t.get();
    ar << boost::serialization::make_nvp("px", t_ptr);
}

template<class Archive, class T>
inline void load(
    Archive & ar,
    std::shared_ptr< T > &t,
    const unsigned int /*file_version*/
){
    // The most common cause of trapping here would be serializing
    // something like shared_ptr<int>.  This occurs because int
    // is never tracked by default.  Wrap int in a trackable type
    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
    T* r;
    ar >> boost::serialization::make_nvp("px", r);
    ar.reset(t,r);
}

template<class Archive, class T>
inline void serialize(
    Archive & ar,
    std::shared_ptr< T > &t,
    const unsigned int file_version
){
    // correct shared_ptr serialization depends upon object tracking
    // being used.
    BOOST_STATIC_ASSERT(
        boost::serialization::tracking_level< T >::value
        != boost::serialization::track_never
    );
    boost::serialization::split_free(ar, t, file_version);
}

} // namespace serialization
} // namespace boost

#endif // BOOST_SERIALIZATION_STD_SHARED_PTR_HPP

Вы можете увидеть различия с <boost/serialization/shared_ptr.hpp> здесь

В основном,

  • переименовано включает охранник
  • изменено boost::shared_ptr на std::shared_ptr
  • включено <memory> вместо <boost/shared_ptr.hpp>
  • защищено null_deleter от переопределения в случае, если вы также использовать boost::shared_ptr
  • удалено BOOST_SERIALIZATION_SHARED_PTR_132_HPP - что бы это ни значило?

Пока что, кажется, это работает просто отлично.

0
ответ дан 28 November 2019 в 23:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: