2010-07-23 2 views
3

Я должен сериализовать libkdtree ++ в моей программе, древовидные структуры кратко описана следующим образом: отчетыСериализации с использованием подталкивания :: сериализаций

struct _Node_base { 
    _Node_base * _M_parent, *_M_left, * _M_right; 

    template<Archive> 
    serialize(Archive &ar, const unsigned int version) { 
    ar & _M_left & _M_right; 
    } 
} 

template<typename V> 
struct _Node : public _Node_base { 
    typedef V value_type; 
    value_type value; 
    template<Archive> 
    serialize(Archive &ar, const unsigned int version) { 
    ar.register_type(static_cast<_Node*>(NULL)); 
    ar & boost::serialization::base_object<_Node_base>(*this); 
    ar & value; 
    } 
} 

struct Tree { 
    _Node * root; 
    template<Archive> 
    serialize(Archive &ar, const unsigned int version) { 
    ar & root; 
    } 
} 

Этой программы «ошибка потока». Но из «файла serailzed» в нем отсутствуют поля значений для дочерних узлов корней. Таким образом, я думаю, что возможно, что BaseNode сериализует _M_left и _M_right указатель. Однако, поскольку _Node_base понятия не имеет о типе значения _Node, поэтому сложно добавить «ar.register_type» в _Node_base.serialize().

+0

Этот код не компилируется. 'Node' должен быть подклассом' BaseNode', 'left' и' right' должен быть ptrs, 'value_type' undeclared,' serialize' missing return type и т. Д. И т. Д. Пожалуйста, разместите некоторый настоящий код (который компилируется). –

ответ

0

следующее решение libkdtree ++ & повышения :: сериализации кажется работа:

// KDTree::_Node 
friend class boost::serialization::access; 
template<class Archive> 
//void serialize(Archive & ar, const unsigned int version) 
void save(Archive & ar, const unsigned int version) const 
{ 
    ar.register_type(static_cast< _Link_type>(NULL)); 
    ar & boost::serialization::base_object<_Node_base>(*this); 
    _Link_type left = static_cast<_Link_type>(_M_left); 
    _Link_type right = static_cast<_Link_type>(_M_right); 
    ar & left & right; 
    ar & _M_value; 
} 


template<class Archive> 
void load(Archive & ar, const unsigned int version) 
{ 
    ar.register_type(static_cast< _Link_type>(NULL)); 
    ar & boost::serialization::base_object<_Node_base>(*this); 
    _Link_type left, right; 
    ar & left & right; 
    ar & _M_value; 
    if (left) { 
     left->_M_parent = this; 
    } 
    if (right) { 
     right->_M_parent = this; 
    } 
    _M_left = left; 
    _M_right = right; 
} 

BOOST_SERIALIZATION_SPLIT_MEMBER() 
+0

I put мое решение на http://github.com/eddyxu/kdtree-serialization – eddyxu

0

pointer_conflict исключение documentation состояния (СИК):

pointer_conflict, // an attempt has been made to directly 
         // serialization::detail an object 
         // after having already serialzed the same 
         // object through a pointer. Were this permited, 
         // it the archive load would result in the 
         // creation of an extra copy of the obect. 

Я думаю, что конфликт возникает там, где каждый сериализации с помощью PTR в BaseNode::serialize и путем прямого объекта, выражение *Node, в Node::serialize. Однако, поскольку функция base_object принимает ссылку, а не ptr, я не уверен, как вы могли бы избежать этого.

Одна из возможностей состоит в том, чтобы не сериализовать parent ptr. Вместо этого, после десериализации, выполните прогулку по дереву и исправьте родительские ptrs, чтобы указать на родительский узел. Например. добавьте следующий метод BaseNode:

void fix (BaseNode* parent = 0) 
{ 
    this->parent = parent; 
    if (left != 0) 
     left->fix (this); 
    if (right != 0) 
     right->fix (this); 
} 

Тогда просто позвоните root->fix()

+0

У него все еще есть ошибка потока, возникающая из процесса декодирования ... Я думаю, что это – eddyxu

+0

friend class boost :: serialization :: access; шаблона <класс Архив> аннулируется сериализации (Архив & ар, сопзИте неподписанные INT версия) { // сериализовать информацию базового класса ar.register_type (static_cast <_Node*> (NULL)); ar & boost :: serialization :: base_object <_Node_base> (* this); ar & _M_value; } Я добавил эту функцию в libkdtree :: _ Node, однако, я думаю, что проблема здесь в функции serialize() в base_object не будет правильно сериализовать _left, _right point, которые просто обрабатывают их как указатель _Node_base * – eddyxu