2010-02-17 5 views
2

J'essaie d'ajouter un boost :: ptr_vector à un std :: deque, en utilisant push_back(). Quand je fais, je reçois un BOOST :: ASSERT pour la discordance de typeid.Ajout de boost :: ptr_vector à deque, typeid mismatch

Dans "boost_ptr_container_clone_allocator"

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

De TotalView, res et r:

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

Ils regardent la même chose pour moi.

Le ptr_vector J'essaie d'ajouter a des instances de diagnostic_database_loader::JointDiagnosticDBClass, qui est dérivé du diagnostic_database_loader::DiagnosticDBClass ci-dessus.

J'ai imprimé la typeid des éléments dans le ptr_vector

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

J'ai essayé de reproduire ce avec un programme de test simple, mais je ne suis pas le même problème.

#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; 
} 

Le programme de test fonctionne correctement.

Est-ce que quelqu'un sait comment
* Reproduire le problème dans le code de test?
* Résoudre le problème dans le vrai programme?

Si quelqu'un veut le code complet:
https://code.ros.org/svn/wg-ros-pkg/trunk/sandbox/diagnostic_database_loader

Répondre

1

Vous devriez spécialiser les fonctions new_clone et delete_clone comme décrit dans le documentation.

Sinon, vous pouvez spécifier votre propre clone allocator comme second argument de 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... 
} 
+0

Merci, j'ai essayé la méthode « ItemCloner », et cela a fonctionné dans mon programme. Quelle implémentation est préférée? Il semble que spécifier le Cloner dans chaque vecteur est un peu lourd. Avec ces cloneurs, cela signifie-t-il que nous faisons une copie pour chaque version de tableau? – kevbo

+0

@kevbo: Chaque fois qu'un 'ptr_vector' est copié, ses données internes sont également copiées. Si vous ne voulez pas de ce comportement, vous devriez probablement utiliser 'vector >' à la place. – dalle