views:

99

answers:

6

I'm trying to use RAII concepts with an STL container of ofstream objects. For example:

int main(int argc, char**argv)
{
  std::deque<std::ofstream> sList;

  sList.push_back(std::ofstream()); // tried variations such as *(new ofstream())
  sList[0].open("test1.txt");
  sList[0] << "This is a test";
  sList[0].close();
}

However, no matter how I try to tweak the code and declarations, the compiler always complains. Apparently the copy constructor for std::basic_ios, which lives inside of streams, is private. Are there any easy plian C++/STL solutions to doing this using RAII, or do I need to get some type of smart pointer involved?

+4  A: 

Stream objects cannot be copied, so you can't create containers of them - you will have to use pointers of some sort.

deque <ofstream *> files;
files.push_back( new ofstream );
// and later delete it, or use a smart pointer
anon
+1  A: 

In the interest of keeping a file from being written to in multiple places in various parts of the system, streams are noncopyable. A smart pointer is probably the way to go here.

Joel
Though all the answers here have good info, I liked your answer because it explains the rationale as to WHY a file stream is not copyable. Well done!
Ogre Psalm33
+4  A: 

Standard library containers store copies of the values, not the values themselves. As such, you will have to use an object that can be copied (a smart pointer in this case).

An alternative would be boost::ptr_vector which acts as a vector of pointers precisely for this kind of situation.

Victor Nicollet
+2  A: 

You probably need to get a smart pointer of some sort involved. One of the requirements of containers (at least in C++) is that to put something in a container, it must be copyable -- and streams are not copyable.

FWIW, in C++0x, this will be possible directly -- it allows containers to hold items that are movable but not copyable, and streams will be movable (but still not copyable).

Jerry Coffin
A: 

Try using boost::ref. It's meant to store references without copying them. http://www.boost.org/doc/libs/1_43_0/doc/html/ref.htm

Scharron
+1  A: 

ofstream has RAII baked in. The destructor of ofstream automagically closes the files so you don't need to.

Use

std::vector<boost::shared_ptr<std::ofstream>> 

as your container and all the file handles will be deleted when you drop the vector.

Do not use a container of std::auto_ptr!

bradgonesurfing
Yes, I've heard not-so-good things about std::auto_ptr. :-)
Ogre Psalm33
There is nothing wrong with std::auto_ptr. Just don't use it for things it is not meant to be used for. auto_ptr moves the contained pointer on copy. So if you have.http://gist.github.com/498683When p goes out of scope it deletes the object foo.
bradgonesurfing
There is nothing wrong with auto_ptr. It has specific use case and you just need to know the appropriate time and place where to use it.
Martin York
I should have qualified my statement. Since a lot of STL (including containers) makes copies of the objects being used, auto_ptr is not a good fit in this situation, since no two auto_ptrs should own the same element.
Ogre Psalm33