1
struct Obj
{
    Obj(P *p, int i): m_p(p), m_info(info) {}
    std::auto_ptr<P> m_p;
    int m_info;
};

std::vector<Obj> objects; // error C2558: struct 'Obj' : no copy constructor available...

The problem here resides in auto_ptr, I guess. Everybody knows that it's a bad thing to push auto_ptr into containers, and it's also a bad to push those who holds auto_ptr into containers. It I had no m_info field, I would use boost::ptr_vector<P> objects

How would you suggest to sort it out?

Nick
  • 3,205
  • 9
  • 57
  • 108
  • Why are you using `auto_ptr` at all? Are you using a very old compiler? – jalf Nov 23 '12 at 12:18
  • 1
    I don't know what's the problem with `auto_ptr`, haven't used it, but am pretty sure `shared_ptr` is safe to store in containers. – Violet Giraffe Nov 23 '12 at 12:19
  • Possibly a dumb question, but why exactly is pushing auto_ptr's into vectors bad? – Gaminic Nov 23 '12 at 12:20
  • 1
    @Garminic : that's a very good question, and there's a very good reply on SO : http://stackoverflow.com/questions/111478/why-is-it-wrong-to-use-stdauto-ptr-with-standard-containers :) – Dinaiz Nov 23 '12 at 12:24
  • 1
    @Gaminic Because `auto_ptr`'s copying has move semantics, and the standard library containers are allowed to assume copying has copy semantics. – Angew is no longer proud of SO Nov 23 '12 at 12:24
  • std::auto_ptr is not compatible with the standard containers. I am surprised the code compiled. But this is explicitly documented in the standard. It is caused because the std::auto_ptr is not copyable (ie the result of a copy is not a copy but actually a transfer of ownership). The standard containers require that the stored type be copyable. – Martin York Nov 23 '12 at 15:22

2 Answers2

0

I assume your class Obj is suppose to take ownership of p. Why not, simply use a normal pointer, with RAII (assign m_p in Obj(P *p, int i) and delete it in ~Obj() ) ?

Or you could easily create a ScopedPointer class, like that one http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/scoped_ptr.htm

Dinaiz
  • 2,213
  • 4
  • 22
  • 32
  • 1
    Using a smart pointer instead of a raw pointer is a good idea. The problem here is specifically `std::auto_ptr`, which does not work well with standard containers. – Gorpik Nov 23 '12 at 12:26
  • Taking your advice at face value would result in writing a broken class that does not, in fact, follow RAII. You should make an explicit mention of the rule of three. – Luc Danton Nov 23 '12 at 12:33
  • Both parts of you advice are not to go. I do not want to use raw pointers, and scoped_ptr cannot be used in C++ Standard Library container. – Nick Nov 23 '12 at 12:38
  • @Nick : Well, what I meant by RAII was actually what utnapistim said in the answer which you accepted so I might not be completely wrong ;) . And when I said, create a ScopedPointer, I meant write your own scoped pointer class which complies with stl containers, not use boost's . Just provided boost as an example – Dinaiz Nov 23 '12 at 15:22
  • @Luc Danton : yes you're right, I thought it would be obvious that he would have to deal with copy as well, but it's not that obvious. My bad – Dinaiz Nov 23 '12 at 15:23
  • @Dinaiz: First, thank you for your answers. I never mentioned that you were 'completely wrong'. My intention was to write a minimum of custom code and use a maximum of stl or boost capabilities. @utnapistim mentioned `shared_ptr` that was exacly what I needed - that's why I accepted his answer, not yours. – Nick Nov 23 '12 at 15:35
  • No prob at all, I also think it's better to use trusted libraries like boost rather than one's own implementation :) – Dinaiz Nov 23 '12 at 16:04
0

You can either manage the raw pointer yourself (allocate in constructor, deallocate in destructor and implement copy semantics - conformant with RAII) or change the type of the pointer from std::auto_ptr to std::shared_ptr / boost::shared_ptr / something else.

utnapistim
  • 26,809
  • 3
  • 46
  • 82