Древовидная структура сериализации с использованием boost :: serialization - PullRequest
3 голосов
/ 23 июля 2010

Я должен сериализовать 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 ().

Ответы [ 2 ]

0 голосов
/ 05 августа 2010

Следующее решение для libkdtree ++ & boost :: serialization кажется работающим:

// 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 голосов
/ 23 июля 2010

Исключение pointer_conflict документация состояния (sic):

    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 ()

...