void read_foo (std::ifstream& out);
void write_foo (std::ofstream& out);
I have these two functions where one is supposed to read from a file, and the other is supposed to write to one.
Everything works having the below snippets;
std::ifstream ifs ("filename.txt");
read_foo (ifs);
std::ofstream ofs ("filename.txt");
write_foo (ofs);
However, if I try to use a std::fstream
, so I can call both functions with the same stream, it doesn't compile, and the compiler spits out a lot of error messages.
fstream
to an ifstream&
, or ofstream&
?#include <fstream>
void read_foo (std::ifstream& out);
void write_foo (std::ofstream& out);
int main () {
std::fstream fs ("filename.txt");
read_foo (fs);
write_foo (fs);
}
foo.cpp: In function ‘int main()’:
foo.cpp:9:16: error: invalid initialization of reference of type ‘std::ifstream& {aka std::basic_ifstream<char>&}’ from expression of type ‘std::fstream {aka std::basic_fstream<char>}’ read_foo (fs);
^
foo.cpp:3:7: note: in passing argument 1 of ‘void read_foo(std::ifstream&)’ void read_foo (std::ifstream& out);
foo.cpp:10:16: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from expression of type ‘std::fstream {aka std::basic_fstream<char>}’
write_foo (fs);
^
foo.cpp:4:6: note: in passing argument 1 of ‘void write_foo(std::ofstream&)’ void write_foo (std::ofstream& out);
Since a std::fstream
is not derived from either std::ofstream
, nor std::ifstream
, the reference is not "compatible" with the instance of std::fstream
.
Use std::istream&
and std::ostream&
, instead of std::ifstream&
and std::ofstream&
(respectively).
void write_data (std::ostream&);
void read_data (std::istream&);
As the compiler is trying to tell you; std::fstream
does not inherit from std::ifstream
, therefore you cannot initialize a reference to the latter with a value of the former.
I've stumbled upon several developers who seem to assume that std::fstream
, behind the scenes, is some sort of direct merge between a std::ifstream
, and a std::ofstream
, and that it is implemented by deriving from both.
When asked why they think that is the case, many think that the answer can be summed up with; "because it makes sense, right?"
Imagine that we have three siblings; Ivan, Owen, and John, living in a family where reading and writing is everything.
All brothers were born with a gift;
Just because John can do both of the things his brothers can, doesn't mean that they are his parents - they are, after all; his brothers.
All three brothers has inherited their certain traits from other relatives, not each other.
std::fstream
is not built "on top of" std::{i,o}fstream
, even though they share certain parts of their individual inheritance tree.
src: http://en.cppreference.com/w/cpp/io
When accepting a stream in generic code you should not care about the "real" type of the underlying stream.
Does it really matter if we pass in a std::stringstream, std::fstream, or std::ofstream to our function which writes some output data to a stream? No, all we care about is the ability to read/write.
We express this by forming a reference to either std::istream
, std::ostream
, or std::iostream
, when we need a stream which can;read, write, or both, respectively.
( Note: IF it's not obvious: Ivan is an ifstream, Owen an ofstream, and John a fstream. )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With