Добавление boost :: ptr_vector в deque, несоответствие typeid - PullRequest
2 голосов
/ 17 февраля 2010

Я пытаюсь добавить boost :: ptr_vector в std :: deque, используя push_back (). Когда я это делаю, я получаю BOOST :: ASSERT за несоответствие типов.

В "boost_ptr_container_clone_allocator"

     T* res = new T( r );
     BOOST_ASSERT( typeid(r) == typeid(*res) &&
                   "Default new_clone() sliced object!" );
     return res;

Из TotalView, res и r:

Function "boost::new_clone<diagnostic_database_loader::DiagnosticDBClass>":
r:                                    (diagnostic_database_loader::DiagnosticDBClass  const &)
Local variables:
res:                                  0x082534f8 -> (diagnostic_database_loader::DiagnosticDBClass)

Они выглядят одинаково для меня.

У ptr_vector, который я пытаюсь добавить, есть экземпляры diagnostic_database_loader::JointDiagnosticDBClass, полученные из diagnostic_database_loader::DiagnosticDBClass выше.

Я распечатал typeid элементов в ptr_vector

boost::ptr_vector<DiagnosticDBClass> items(loader->getData());
>>> N26diagnostic_database_loader22JointDiagnosticDBClassE

Я пытался воспроизвести это с помощью простой тестовой программы, но у меня нет такой же проблемы.

#include "iostream"
#include <boost/ptr_container/ptr_vector.hpp>
#include <deque>

class Item
{
public:
  int my_val;
  Item() : my_val(1) { }

  int getMyVal() { return my_val; }
};
class SmallItem : public Item
{
public:
  SmallItem() : Item() { my_val = 2; }
};

class TinyItem : public SmallItem
{
public:
  TinyItem() : SmallItem() { my_val = 3; }
};

class MyClass
{
private:
  boost::ptr_vector<SmallItem> items_;  

public:
  MyClass() 
  { 
    for (int i = 0; i < 10; ++i)
    {
      SmallItem *it = new TinyItem();
      items_.push_back(it);
     }
  }

 std::auto_ptr<boost::ptr_vector<SmallItem> > getData() { return items_.release(); }
 };

std::deque<boost::ptr_vector<SmallItem> > Buffer;

int totalItems(boost::ptr_vector<SmallItem> &items)
{
  int total = 0;
  boost::ptr_vector<SmallItem>::iterator it;
  for (it = items.begin(); it != items.end(); ++it)
    total += (*it).getMyVal();
  return total;
}

int main(int argc, char **argv)
{
  MyClass cls;

  boost::ptr_vector<SmallItem> items(cls.getData());

  std::cout << "SmallItem typeid   " << typeid(items[0]).name() << std::endl;

  fprintf(stdout, "I found %d total!\n", totalItems(items));

  Buffer.push_back(items);

  fprintf(stdout, "I pushed back into the deque!\n");

   boost::ptr_vector<SmallItem> items2 = Buffer.front();
   Buffer.pop_front();
   fprintf(stdout, "I still found %d total in the new vector!\n", totalItems(items2));

  items2.release();
  fprintf(stdout, "I found %d total after I released!\n", totalItems(items2));

  return 0;
}

Тестовая программа работает нормально.

Кто-нибудь знает, как
* Воспроизвести проблему в тестовом коде?
* Исправить проблему в реальной программе?

Если кому-то нужен полный код:
https://code.ros.org/svn/wg-ros-pkg/trunk/sandbox/diagnostic_database_loader

1 Ответ

1 голос
/ 17 февраля 2010

Вы должны специализировать функции new_clone и delete_clone, как описано в документации .

В качестве альтернативы вы можете указать свой собственный клонатор в качестве второго аргумента ptr_vector:

class Item
{
public:
  int my_val;
  Item() : my_val(1) { }

  Item* clone() const
  {
    Item* item = do_clone();
    BOOST_ASSERT(typeid(*this) == typeid(*item) &&
                 "do_clone() sliced object!");
    return item;
  }

  int getMyVal() { return my_val; }

private:
  // new virtual member function, overload in all derived classes.
  virtual Item* do_clone() const
  {
    return new Item(*this);
  }
};

class SmallItem : public Item
{
public:
  SmallItem() : Item() { my_val = 2; }

private:
  virtual Item* do_clone() const
  {
    return new SmallItem(*this);
  }
};

struct ItemCloner
{
  static Item* allocate_clone(const Item& item)
  {
    return item.clone();
  }

  static void deallocate_clone(const Item* item)
  {
    delete item;
  }
};

int main()
{
   boost::ptr_vector<Item, ItemCloner> items;
   // and so on...
}
...