Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

I got a strange error message when using fstream!

23 views
Skip to first unread message

Wader

unread,
Mar 31, 2008, 5:31:02 AM3/31/08
to
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

class MyObj {
public:
int data;
ifstream in;
};

typedef std::vector<MyObj> MyObjVector;

int main(int arc, char* argv[]) {
MyObjVector myVector;

MyObj obj;
obj.data = 10;
obj.in.open("test.txt");

myVector.push_back(obj);
}

In the code above, I want to use a vector of class MyObj, which have a
ifstream object, but I got a message says that I can't access the
private memeber of ios_base, both in MinGW and Visual C++, but if a
commented the line
myVector.push_back(obj);
all thing is OK, can't any one help me!

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

David Pol

unread,
Mar 31, 2008, 12:04:16 PM3/31/08
to
On 31 mar, 11:31, Wader <WaderC...@gmail.com> wrote:
> #include <fstream>
> #include <iostream>
> #include <vector>
> using namespace std;
>
> class MyObj {
> public:
> int data;
> ifstream in;
>
> };
>
> typedef std::vector<MyObj> MyObjVector;
>
> int main(int arc, char* argv[]) {
> MyObjVector myVector;
>
> MyObj obj;
> obj.data = 10;
> obj.in.open("test.txt");
>
> myVector.push_back(obj);
>
> }
>
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

Hello,

In order to be stored in a std::vector<>, a type must meet the
requeriments of CopyConstructible and Assignable types. Streams do not
satisfy these requeriments, as the copy constructor and assignment
operator for std::basic_ios<> (a base class that provides common
functionality and state required by all streams) are private and not
defined.

Note that you do not define a copy constructor for MyObj. So, as soon
as you try to use one (in your case, by pushing back an instance of
MyObj into a std::vector<> (1), but obviously the compiler error would
be the same if you tried to construct a second instance of MyObj from
the original instance), the compiler tries to generate a copy
constructor for MyObj. And a compiler-generated copy constructor
simply copies each non-static data member of the source object over to
the target object, which in this case is not possible because
std::ifstream does not define a copy constructor (specifically, the
compiler tries to generate a copy constructor for
std::basic_ifstream<>, which in turn tries to call the copy
constructors of its base classes; the whole process ending up in a
rejected call to the private copy constructor declared in
std::basic_ios<>).

(1) Of course, defining a copy constructor for MyObj would not be
enough for this type to meet the mentioned requeriments to be stored
in a std::vector<>.

Regards,
David

Oncaphillis

unread,
Mar 31, 2008, 12:02:52 PM3/31/08
to
Wader wrote:
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

push_back tries to append a *copy* of MyObj into
the vector. So MyObj has to provide a copy constructor.
Since you did not provide a copy constructor.
C++ invokes it's own by trying to invoke the
copy constructor on all data members of MyObj.
This ends up into invoking a copy constructor on
ios_base (the base class of ifstream) which is
intentionally declared private.


So either you declare your own copy ctor on MyObj
which somehow deals with the 'copying' of ifstream
(meaning implementing your desired semantics) or
you kick out the ifstream).

I don't know what your intentions are to hold
a couple of ifstreams in a vector.

Hope that helps

O.

Daniel Krügler

unread,
Mar 31, 2008, 12:43:04 PM3/31/08
to
On 31 Mrz., 11:31, Wader <WaderC...@gmail.com> wrote:
> #include <fstream>
> #include <iostream>
> #include <vector>
> using namespace std;
>
> class MyObj {
> public:
> int data;
> ifstream in;
>
> };
>
> typedef std::vector<MyObj> MyObjVector;
>
> int main(int arc, char* argv[]) {
> MyObjVector myVector;
>
> MyObj obj;
> obj.data = 10;
> obj.in.open("test.txt");
>
> myVector.push_back(obj);
> }
>
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

std::vector requires that any feasible element type (value type) must
be CopyConstructible (and Assignable). This is a general Container
requirement of the current C++ standard, see
[lib.container.requirements]/3.

The member in of type std::ifstream does not fulfill this
requirement,
which follows by implication, because it's base class basic_ios is
not.

One possible workaround for you might be to use a
boost::shared_ptr<ifstream> instead and to use the free store ("new")
to
allocate the stream.

HTH & Greetings from Bremen,

Daniel Krügler

Ulrich Eckhardt

unread,
Mar 31, 2008, 12:43:04 PM3/31/08
to
Wader wrote:
> class MyObj {
> public:
> int data;
> ifstream in;
> };
>
> typedef std::vector<MyObj> MyObjVector;

std::vector requires that its elements are copyable and assignable. Since
iostreams are neither copyable nor assignable, objects containing them
aren't either (at least not unless you redefine these operations). From
that follows that you can't use MyObj as element type of std::vector.

> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base

Two things:
1. It is typically a good idea to quote error messages.
2. The copy constructor is declared private in order to prevent copying,
that's why you get the error message.

Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

Olivier Langlois

unread,
Apr 1, 2008, 7:15:14 AM4/1/08
to
> class MyObj {
> public:
> int data;
> ifstream in;
>
> };
>
> typedef std::vector<MyObj> MyObjVector;
>
> int main(int arc, char* argv[]) {
> MyObjVector myVector;
>
> MyObj obj;
> obj.data = 10;
> obj.in.open("test.txt");
>
> myVector.push_back(obj);
>
> }
>
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

It is because ifstream is not copyable and one STL containers
requirement for contained type is that they can be copyable with the
copy constructor and/or the assignment operator.

The default and the copy constructors + assignement operator are
automatically generated by the compiler if they are not explicitly
declared in a user defined class (like in your MyObj class). The only
exception where the compiler will not generate those functions is if
generating them would create an error.

However, if in your code you still try to copy an object, the compiler
will give you the reason why it cannot create the copy constructor.

Mix that with the fact the methods of a class template is not
instantiated before they are used in your code and this totally
explain the behavior that you are experiencing.

An additionnal interesting observation is that the reason why the
compiler does not take the same liberty to optimize out unused
automatically generated functions like it does for methods of class
templates, it is that templates usage is totally determined at compile-
time where as you could compile and store an ordinary class into a
library and link with it at a later time. When the compiler compiles
the ordinary class, it has no idea whether or not the automatically
generated functions will be needed so it always generates them, if
possible of course.

Greetings,
Olivier Langlois
http://www.olivierlanglois.net
http://blog.olivierlanglois.net

Bo Persson

unread,
Apr 1, 2008, 7:13:07 AM4/1/08
to
Wader wrote:
> #include <fstream>
> #include <iostream>
> #include <vector>
> using namespace std;
>
> class MyObj {
> public:
> int data;
> ifstream in;
> };
>
> typedef std::vector<MyObj> MyObjVector;
>
> int main(int arc, char* argv[]) {
> MyObjVector myVector;
>
> MyObj obj;
> obj.data = 10;
> obj.in.open("test.txt");
>
> myVector.push_back(obj);
> }
>
> In the code above, I want to use a vector of class MyObj, which
> have a ifstream object, but I got a message says that I can't
> access the private memeber of ios_base, both in MinGW and Visual
> C++, but if a commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

You can't copy stream objects. Think about it - what does it mean to
make a copy of a file stream, does it create a new file, or what?

To stop you from doing this, one of the base classes of all the
streams has its copy constructor and assignment operator made private.

Bo Persson

Martin York

unread,
Apr 1, 2008, 8:13:04 AM4/1/08
to
On Mar 31, 2:31 am, Wader <WaderC...@gmail.com> wrote:
> #include <fstream>
> #include <iostream>
> #include <vector>
> using namespace std;
>
> class MyObj {
> public:
> int data;
> ifstream in;
>
> };
>
> typedef std::vector<MyObj> MyObjVector;
>
> int main(int arc, char* argv[]) {
> MyObjVector myVector;
>
> MyObj obj;
> obj.data = 10;
> obj.in.open("test.txt");
>
> myVector.push_back(obj);
>
> }
>
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

{ edits: quoted clc++m banner removed please don't quote extraneous material -mod }

Stream objects are not copyable.
As a result objects that contain streams are also not copyable.

Therefore you can not put them in the standard containers. As objects
are copy constructed into the container. You could modify your code so
that it uses pointers/references to a stream (Just remember to clean
up).

Kimon Hoffmann

unread,
Apr 1, 2008, 8:13:04 AM4/1/08
to
Hi,

Wader wrote:
>
> <Code snipped>


>
> In the code above, I want to use a vector of class MyObj, which have a
> ifstream object, but I got a message says that I can't access the
> private memeber of ios_base, both in MinGW and Visual C++, but if a
> commented the line
> myVector.push_back(obj);
> all thing is OK, can't any one help me!

The reason for this error is simple. Objects are never inserted directly
into an STL container, but instead the object is copied into the
container. The std::basic_ios class is non-copyable (which is enforced
by means of a private and unimplemented copy constructor and assignment
operator), and therefor all classes derived from it, which includes all
the filestream classes, are non-copyable as well.

A possible solution to your problem would be to allocate the object on
the heap using operator new, and storing pointers to MyObj instances in
the vector. To make this approach more safe and convenient you might
consider using the Boost.Pointer Container library.

You can find its documentation here:
http://www.boost.org/doc/libs/1_35_0/libs/ptr_container/doc/ptr_container.html

Best regards,
Kimon

0 new messages