Creating my own cin & cout is somewhat pointless, so I just curious about how.
I know that cin and cout are instances of istream/ostream class; however, I've tried some declarations like "std::istream mycin"
but didn't work.
Besides, I read a lot of posts saying that cin and cout are global variables, but we have to access them through std::cin or std::cout. My understanding is that global variables are those declared in the global scope, but cin and cout are obviously in the std namespaces. Which part of my knowledge is wrong? Thanks.
std::cin and std::cout are not just "instances of istream/ostream class". They are also connected to the C++ program's standard input and output stream.
How that happens, how that's done, is not specified by the C++ standard. Your C++ compiler and library does whatever needs to be done to make that happen, and the exact details of the underlying working is implementation defined. Merely declaring two std::istream and std::ostream objects of your own won't, of course, accomplish that by fiat. If you're interested, you can do some research and investigation, and determine how your C++ implementation or library goes about doing this, and reimplement it yourself, with your own instance of std::istream and std::ostream.
std::istream and std::ostream, by themselves, merely implement formatted input and output extraction operations using an underlying instance of a std::streambuf. std::istream and std::ostream's constructor takes a pointer to an instance of a std::streambuf that's used as the underlying input/output source/sink.
So, to summarize, in order to reimplement what std::cin and std::cout does, yourself, it is necessary to:
Implement a subclass of std::streambuf that handles the underlying input and output by using your operating system-specific resources to read or write to your terminal.
Use your std::streambuf subclass to construct an instance of a std::istream and/or std::ostream.
Related
Disclaimer: I am a complete C++ beginner, and if there is a similar answer to this question, please direct me to it, as I may have missed it, not knowing much in the way of theory.
Suppose I have a method which accepts a reference to an ostream:
printAllObjects(std::ostream& os);
I am assuming it makes changes to the ostream, so that one can print the list of all of the objects to a file, say. (I might be wrong here)
Is there any way of seeing what it writes to the ostream? (via cout preferably)?
std::cout is an std::ostream, so just pass std::cout to the function and you'll see what it does:
printAllObjects(std::cout);
This flexibility is the very purpose of accepting a reference to std::ostream!
Other stream types1 inheriting from the std::ostream base include:
std::ofstream (for file output)
std::ostringstream (for string output).
1 That's not to say that std::cout is a type; it's not. It's a special, global instance of std::ostream.
I have an abstract class in my project, its derivatives is used for input/output to different locations.
It has virtual methods read and write.
virtual unsigned read(void *buf, unsigned len) = 0;
virtual void write(const void *buf, unsigned len) = 0;
I need a kind of an adapter between std streams (std::istream and std::ostream) and this class to redirect input/output to these methods.
So, for example, if
mystream << "some output";
is called, it will call the write method.
I guess i should overload std::istream and std::ostream or std::streambuf, but not sure which methods.
What is the better way to implement this?
There are lots of simple but not flexible ways of doing it. Most of these solution will not leverage istream or ostream. For instance, overloading the << operator is one way. The drawback is that you will have to implement this operator for all the usual types, and for all the standard manipulators, and so on. It may become a great burden.
This is sad because the whole thing about istream and ostream is only to parse and format not to do input or output. The I/O responsibility is given to the streambuf. And your task calls for a custom implementation of streambuf which uses your read and write methods.
The discussion is too long for such a small format as a stackoverflow answer but you can find good pointers in the following references.
References
http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
http://en.cppreference.com/w/cpp/io/basic_streambuf
http://www.amazon.com/Standard-Library-Tutorial-Reference-2nd/dp/0321623215/ref=sr_1_1?ie=UTF8&qid=1442329302&sr=8-1&keywords=josuttis , this book contains a chapter dedicated to streambuf implementation.
Note
As advised, using boost.iostreams maybe a good fit, but I don't know it enough.
You might want to take a look at the boost iostreams library. It provides a framework that makes it easier to define iostreams with custom sources and sinks (input and output devices).
I am a fan of std::stringstream, and perhaps your class could make use of it.
std::stringstream ss;
ss << "some output";
from which something would invoke write like:
write(ss.str().c_str(), ss.str().size());
You will have to figure out how to connect the two, but this has the advantage of providing all stream io.
On the other hand, directly implementing operator << and >> is not too difficult.
I guess i should overload std::istream and std::ostream or
std::streambuf, but not sure which methods.
Start with the method you need first, then add functionality as you identify the requirements.
I've read about custom streams for C++ but it seems that generally people inherit from std::streambuf, std::istream, and std::ostream. By inspecting those type's declarations it becomes clear that these are meant for characters:
typedef basic_streambuf<char> streambuf;
The docs confirm this:
Input stream objects can read and interpret input from sequences of
characters.
Obviously, that makes sense. I'm wondering what would be the correct way of implementing a stream for other types. I do not want to allow text but other forms of binary input/output (I have specific formats). The obvious step seems to be to inherit the basic variants of the above (basic_streambuf, basic_istream, and basic_ostream) and use whatever type I see fit as the template parameter. I failed to find confirmation that this would be the right procedure. So, is it?
Edit for clarification: I have a class called Segment. These streams will send/receive segments and only segments over a WiFi connection as these are used in the communication protocol. Sending anything else would break the protocol. This means that the stream cannot support other types.
This is not an answer to your question in terms of inheriting from std::basic_* with non-char types. But following the comments and given your application, I am questioning the need to reimplement the whole standard stream machinery for your Segment type, when you can simply define a class with a stream operator:
class SegmentStream
{
public:
SegmentStream& operator<< ( const Segment& s );
}
Better yet you could clarify your code by defining methods send and recv instead of >>, <<.
Or perhaps you could explain why this would not be sufficient and why you specifically want to use standard streams?
So, I've been trying to be more rigorous with making any passed parameters that shouldn't be touched by a function const.
One situation I've encountered in some of my C++ code is the case where the object may change, but where I want to "lock out" functions from access certain key functionality of the object. For example, for an std::ifstream file handle, I may wish to prevent the function from closing the file.
If I pass it as a const &, the const part keeps me from performing standard file i/o, it seems.
e.g. I want something along the lines of
void GetTags(Arr<std::string> & tags, std::ifstream const& fileHandle)
...but written in such a way to allow file i/o but not open/close operations.
Is there any good/reliable way to do this in C++? What would be considered best practice?
This has already been done for you by the standard library design: Pass a reference to the base class std::istream instead, which does not have a notion of opening or closing - it exposes only the stream interface.
void stream_me(std::istream & is);
std::ifstream is("myfile.txt");
stream_me(is);
In your place I'd just pass a std::istream instead.
You could wrap the ifstream in an object that only exposed the functionality that you wished the caller to be able to use.
However, if you have a bunch of different functions, each with a different subset of ifstream's functionality, you'll end up with lots of different wrapper classes; so I don't see this as a general solution.
I think the best way would be to wrap the ifstream in a new class which only has member functions corresponding to the functionality you wantGetTags to have access to. Then pass that not the ifstream as the second argument to GetTags.
Some days ago, I decided that it would be fun to write a streambuf subclass that would use mmap and read-ahead.
I looked at how my STL (SGI) implemented filebuf and realized that basic_filebuf contains a FILE*. So inheriting from basic_filebuf is out of the question.
So I inherited from basic_streambuf. Then i wanted to bind my mmapbuf to a fstream.
I thought the only thing that I would have to do would be to copy the implicit interface of filebuf... but that was a clear mistake. In the SGI, basic_fstream owns a basic_filebuf. No matter if I call basic_filestream.std::::ios::rdbuf( streambuf* ), the filestream completely ignores it and uses its own filebuf.
So now I'm a bit confused... sure, I can create my own mmfstream, that would be the exact copy/paste of the fstream but that sounds really not DRY-oriented.
What I can't understand, is: why does fstream is so tightly coupled with filebuf, so that it is not possible to use anything else than a filebuf? The whole point of separating streams and bufs is that one can use a stream with a different buffer.
Solutions:
=> filestream should rely on the implicit interface of filebuf. That is, fstream should be templated by a streambuf class. That would allow everyone to provide its own streambuf subclass to a fstream as long as it implements filebuf's implicit interface. Problem: we cannot add a template parameter to fstream since it would break template selectors while using fstream as template template parameter.
=> filebuf should be a pure virtual class without any additional attributes. So that one can inherit from it without carrying all its FILE* garbage.
Your ideas on the subject ?
In the IO streams' design, most of the actual streams' functionality (as opposed to the stream buffers' functionality) is implemented in std::basic_istream, std::basic_ostream, and their base classes. The string and file stream classes are more or less just convenience wrappers which make sure a stream with the right type of buffer is instantiated.
If you want to extend the streams, you almost always want to provide your own stream buffer class, and you almost never need to provide your own stream class. .
Once you have your own stream buffer type, you can then make it the buffer for any stream object you happen to have around. Or you derive your own classes from std::basic_istream, std::basic_ostream, and std::basic_iostream which instantiates your stream buffer and pass it to their base classes.
The latter is more convenient for users, but requires you to write some boiler-plate code for the buffer's instantiation (namely constructors for the stream class).
To answer your question: File streams and file buffer are coupled so tightly because the former only exists to ease the creation of the latter. Using a file stream makes it easy to set it all up.
Using your own stream class to wrap construction of your own stream buffer shouldn't be a problem, since you shouldn't be passing around file streams anyway, but only (references) to the base classes.
Check out mapped_file in the Boost.Iostreams library. I've never used used it myself, but it seems like it might already do what you need.
EDIT: Oops, reread your questions and I see you're doing this for fun. Perhaps you can draw inspiration from Boost.Iostreams?
fstream in itself is not a big class. It inherits from basic_stream to provide support for all the << and >> operations, contains a specialized steambuf that have to be initialized, and the corresponding constructors to pass the parameters to the streambuf constructor.
In a sense, what you wrote about your templated solution is OK. But basic_stream can also be derived into a tcp_stream for example. In that case, the constructors of fstream are a bit useless. Thus you need to provide a new tcpstream class, inheriting from basic_stream with the correct parameters for the constructors to be able to create the tcp_stream. In the end, you wouldn't use anything from fstream. Creating this new tcpstream is a matter of writing 3 or 4 functions only.
In the end, you would derive from the fstream class without any real reason to. This would add more coupling in the class hierarchy, unneeded coupling.
The whole point of std::fstream is that it is a _F_ile based std::stream. If you want an ordinary std::stream backed by your mmstreambuf, then you should create a mmstreambuf and pass it to std::stream::stream(std::streambuf*)