2015-08-17 2 views
2

Следующий фрагмент кода компилирует прекрасно:подталкивания сериализации не работает с shared_ptr <int>

#include <boost/serialization/shared_ptr.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <sstream> 
#include <memory> 

struct A { 
    int i; 

    A(): i(0) {} 
    A(int i): i(i) {} 

    template <typename Archive> 
    void serialize(Archive& ar, const unsigned int) { 
     ar & i; 
    } 
}; 

int main() { 
    auto a = std::make_shared<A>(465); 
    std::stringstream stream; 
    boost::archive::text_oarchive out{stream}; 
    out << a; 
} 

Теперь я хотел бы ожидать, что, если я заменю A с int то он также должен работать.

#include <boost/serialization/shared_ptr.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <sstream> 
#include <memory> 

int main() { 
    auto a = std::make_shared<int>(465); 
    std::stringstream stream; 
    boost::archive::text_oarchive out{stream}; 
    out << a; 
} 

Однако этот код не компилируется, но дает сбой утверждение:

In file included from main.cpp:1:  
/usr/local/include/boost/serialization/shared_ptr.hpp:277:5: error: static_assert failed "boost::serialization::tracking_level<T>::value != boost::serialization::track_never" 
    BOOST_STATIC_ASSERT(
    ^
... 

я делаю что-то неправильно, или это ошибка в Boost,?

+1

@Yakk Если вы сохраните, загрузите 'shared_ptr', они будут указывать на разные места (очевидно, так как вы можете загружать из другой программы). Но если вы несколько раз сериализуете 'shared_ptr' в один архив, загрузите его, загруженные указатели укажут на одно и то же место. Он также работает с голыми указателями и 'unique_ptr's – petersohn

ответ

4

От источника подталкивания коды вокруг этого утверждения:

// 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)); 

В основном, для того, чтобы сериализовать такие вещи, как shared_ptr правильно, заостренные к объектам должны быть централизованно отслеживаются в процессе сериализации (чтобы определить, когда несколько указатели указывают на один и тот же объект, поэтому они не приводят к сериализации двух копий объекта). Однако отслеживание объекта дороже, чем его не отслеживание, поэтому примитивные типы не отслеживаются (предполагается, что из них будет лот). По сути, это делает невозможным сериализовать shared_ptr<primitive_type> без уклонения от источников Boost. Решение, как отмечается в комментарии, состоит в том, чтобы вместо этого сериализовать некоторый UDT , содержащий a int.

+0

И канонический источник для этого - [doc/special.html # objecttracking] (http://tinyurl.com/qasswc9) (например,« _По умолчанию, типы данных, обозначенные как примитивные по значению сериализации класса уровня реализации никогда не отслеживаются.Если желательно отслеживать общий примитивный объект через указатель (например, длинный, используемый как счетчик ссылок), он должен быть завернут в класс/struct, чтобы он был идентифицируемым типом . Альтернатива изменения уровня реализации долгого времени повлияла бы на все длинны, сериализованные во всей программе - возможно, не на то, что можно было бы намереваться._ ») – sehe

Смежные вопросы