Reputation: 18585
iostream
and other stream class are not actually class, but typedef
s, right?
Here is the problem, I tried to initialize a istream
object in initialization list, but unfortunately I got an error, code goes bellow:
class A
{
public:
A(istream &is=cin): ais(is)
{}
private:
istream ais;
};
Can't compile with g++, error:
synthesized method ‘std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)’ first required here
I searched SO, found that, iostream cannot be assigned or copy
. But why cannot I initialize it in the initialization list?
Cuz I think, the initialization list will invoke the object's constructor/copy-constructor, right?
Upvotes: 3
Views: 5829
Reputation: 10280
class A
{
public:
A(istream &is=cin): ais(is)
{}
private:
istream& ais;
};
Notice the member is a reference type. As you've written it, you're making a copy to initialize the member.
Upvotes: 1
Reputation: 182827
Your code attempts to turn one istream
, the one passed to the constructor, into two istream
s, the one that was passed to the constructor and ais
. An istream
object represents that actual stream itself. There is only one stream and there is no way to somehow turn it into two streams.
It's not even clear what that would mean. If there's some data on the stream, does whichever stream reads first get it? Or do they both get it? If so, who or what duplicates it?
An istream
is like a file itself. You cannot turn one file into two files without copying the data from one to the other yourself. You can, however, have as many references or pointers to the same istream
as you want. The solution to your problem is probably to make ais
a reference.
Upvotes: 8
Reputation: 154005
The stream object represent a handle to streams of data. Copying that doesn't make sense. Also, this wouldn't be the right thing to copy only tge base part of a stream: this would be slicing off the interesting bit (although you could get hold of thr actually interesting portion by using the stream buffer).
What you want to initialize in your class if it holds a stream is a reference to the stream:
std::istream& ais;
Of course, this means that some external needs to keep the stream alive as long as you are using it. If this isn't what you want or need you can have your class hold e.g. an std::ifstream
and take a std::string
as constructor argument: if the string is non-empty you'd open the corresponding file. Otherwise you'd set your stream's rdbuf()
to the one from std::cin
:
if (name.empty())
ais.open(name.c_str());
else
ais.rdbuf(std::cin.rdbuf());
Upvotes: 2
Reputation: 19731
In addition to the answers you already got, you can also initialize ais
(as of your definition) with the streambuf of the stream you passed in (of course, the same caveat as with the reference applies: You must ensure that the streambuf stays valid until the object is destructed).
Initializing with the underlying streambuf is probably the closest to copying a stream you can do: While both still read from the same file and use the same buffering (and other processing the streambuf may do), all the formatting and error handling flags are separate.
To initialize ais
with the streambuf, you write:
class A
{
public:
A(std::istream& is = std::cin):
ais(is.rdbuf())
{
}
private:
std::istream ais;
};
Upvotes: 1
Reputation: 122001
You have the member variable declared as:
istream ais;
meaning the copy constructor will be invoked in the initializer list. This is not specific to the initializer list: you can't do this anywhere.
You could change the member variable to be a reference:
istream& ais;
but that means you have to ensure that the istream
to which ais
refers is valid for the lifetime of A
.
Upvotes: 5
Reputation: 129914
iostream and other stream class are not actually class, but typedefs, right?
Yes, but that's not relevant.
But why cannot I initialize it in the initialization list?
Because it can be neither copied nor assigned. Ctor init list is not magical. To create ais
from is
you need to make a copy, and you can't.
Upvotes: 3