Using extraction operator to extract data from a complex class hierarchy - c++

1 - Does it sound like a correct approach to use extraction operators to extract some data not from a file but from a big and complex class hierarchy ?
class ComplexInterface
{
//...
};
struct EXTRACTED_DATA
{
//...
friend ComplexInterface& operator>>(const ComplexInterface& interface, EXTRACTED_DATA& extracted)
{
extracted.m_member = interface.someAccessor().getData();
}
};
Would it be better to simply make it a member method (void extractFromComplexInterface(const ComplxInterface&)) ?
Is there a better solution ?
2 - Would it be possible to handle this extraction as a regular stream operation ? The ComplexInterface would become an istream, implementing some magic function in which it would say "I will send this data, then this and that...". Then, the EXTRACTED_DATA could use its regular extraction operator (friend istream& operator>>(istream&, EXTRACTED_DATA&)) which is already defined to read from a file stream.
If this is possible, how ?

Related

Moving std::istream

I have a Scanner class to tokenize streams of characters coming from files, cin, etc.
class Scanner {
public:
Scanner(std::istream&& c) : input{std::move(c)} {}
private:
std::istream input;
};
This code does not compile because the move constructor of std::istream is protected. I could use a reference to the stream instead, but then, I have no guarantee that someone is not playing with my stream outside of the Scanner class (ss below).
std::string code = "this is code";
std::stringstream ss{code};
Scanner scanner{ss};
Is there a neat way to address this issue, or do people just use std::istream& and hope for the best?
From what I can remember about my work with stream objects.
You need to think about this a bit differently.
class Scanner {
public:
Scanner() {}
virtual void scan(std::istream & p_stream);
};
Your Scanner class could just be focused on scanning the input for whatever, not actually containing it.
Now it can be focused purely on a single task.
Then you need to work out what is the best way for you to keep the stream object alive. I suggest a separate class for that task.
I would have written this as a comment, but there's too much here.

Is it possible to overload operator<< like this? [duplicate]

This question already has answers here:
How to define a static operator<<?
(4 answers)
Closed 9 years ago.
Let's say I have a class called "Logger". The name is self explanatory, it logs stuff. I have a static method, which logs stuff (Logger::log(string msg)).
I wanted to overload the operator <<, so that I could do something like:
Logger << "AW YEAH, I LOVE C++";
I tried to do this, but couldn't. What I managed, was this:
Logger l;
l << ":(";
...
is it possible what I want to do? And if yes, how?
Thank You in advance :)
If Logger is the name of a class then of course you can't do that. Use something like
Logger &log() {
static Logger l;
return l;
}
log() << "And the answer is" << 42;
Assuming you want to leverage the output operators provide by std::ostream you should not try to overload the output operator! Instead, you'd create a suitable stream buffer (i.e., a class derived from std::streambuf) and implement your custom output logic in that class's overflow() and sync() methods. Your logger would then derive from std::ostream and initialize its base class to use your custom stream buffer.
Overloaded operators operate on values, not on types.
Maybe you should rename your class, and then create a suitable global object. For example:
logger.h:
class mylogger { /* ... */ };
extern mylogger logger;
logger.cpp:
#include "logger.h"
mylogger logger;
Usage:
#include "logger.h"
logger << "Done";
Beware of global initialization issues; though; check out your implementation of std::cout for a way to solve this (e.g. with a Schwartz counter).
It is possible, but you need to figure out what interface you really want. One option is to make your Logger be an std::ostream (inheritance) and then things would kind of work out of the box. The alternative is to maintain a logger that is unrelated (no inheritance) to std::ostream, but then you need to provide Logger& operator<<(Logger&,T const &) for any and all types T you want to log. For the particular case of std::string you could do:
Logger& operator<<(Logger& logger, std::string const& msg) {
logger.log(msg); // need not be, and problably should be static
return logger;
}
Making this generic involves as with most generic code in C++ the use of templates:
template <typename T>
Logger& operator<<(Logger& logger, T const & obj) {
// do specific work based on the type, or a completely generic approach:
std::ostringstream st;
st << obj;
logger.log(st.str());
return logger;
}
At this point you might want to consider adding support for manipulators and... well, if you start down this path, it might make more sense not to create the std::ostringstream in each function, but create a single one as a member, then dump all data into that stream and use some manipulator to extract the string and write it (for example on std::flush or std::ends...)
template <typename T>
Logger& operator<<(Logger& logger, T const& obj) {
logger.stream << obj;
return logger;
}
Logger& operator<<(Logger& logger, std::ostream& (*manip)(std::ostream&)) {
logger.stream << manip;
if (manip == static_cast<std::ostream& (*)(std::ostream&)>(std::flush)) {
logger.write(); // flush to disk
}
return logger;
}
// add support for other manipulators...
Then again you might start wondering if it would not be easier to pull some off the shelf logging library and just use it.

Conditional output

I'd like to create a C++ ostream object that only outputs anything if a condition holds true, to use for debugging. What would be the easiest way to do this? I know that boost has classes that make this easy, but I'd like to know if there's a simple way to do it without boost. The documentation makes it seem like subclassing ostream::sentry would make this possible, but I can't find any source saying that's something that you can/should do.
Don't subclass, it's easier to use a wrapper:
class MaybeOstream
{
public:
MaybeOstream(std::ostream& stream_) : stream(stream_), bOutput(true) {}
void enable(bool bEnable) { bOutput = bEnable; }
template<typename T>
MaybeOstream& operator<< (T x)
{
if(bOutput)
stream << x;
return *this;
}
// Add other wrappers around ostream: operator void*, good(), fail(),
// eof(), etc., which just call through to the ostream
private:
std::ostream& stream;
bool bOutput;
}
Take a look at this paper on filtered streambufs.

How do I overload the I/O operators C++

I have created a class that allows the user to input their mailing address, order date, type of cookie ordered and the quantity. There were other errors, but I stayed late and with the assistance of my prof, I have fixed them. Now all that is left is that I need to be able to change code to overload the I/O stream operators so that the objects may be used in standard input and output statements.
I'm not sure what all part of the code everyone will need to see, but I'm going to post the parts I believe are needed for what I'm trying to do.
I need to have it where in the output(), I have cout << order << endl; I will look over the net and will hopefully have it ready by tonight. Thanks for everyone's input.
Was instructed to take down my code due to other students from class copying my code pieces to do their work (knew it was possible but didn't think about it)
However, my code is complete.
Implement two functions:
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co)
basic_istream & operator>> (basic_istream& istr, CookieOrder& co)
the operator<<= function will be called when you use cout << order << endl; and the operator>> function will be called when you use the >> (stream extraction) operator. Be very careful how you implement the stream extraction operator.
You may want to declare either of these as friend to the CookieOrder, as that will allow the function to access the private parts of the class as if the function is a member of the class.
edit to respond to changes in the question
delcare your class as before:
class CookieOrder {
public:
// public methods as before
private:
// private parts as before
};
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co);
basic_istream & operator>> (basic_istream& istr, CookieOrder& co);
Implement the two functions using only the public interface of the CookieOrder class.
For example:
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co)
{
ostr << co.get_customerName() << endl;
/* the rest of the output */
}
These functions are not members of the CookieOrder class, they are normal functions with no special access to the CookieOrder class or instanaces of the class.
As far as comparison is concerned, you'd be better off comparing all upper or all lower (rather than each word's first letter upper), it's simpler to set things that way.
Moreover you should get into the habit of putting braces around code
Why do you have a magic number of 6 in your loop? Especially when you only have five (5) elements.
Perhaps the loop should be
...
int loop_size = sizeof(flavors)/sizeof(flavors[0]);
for (int i = 0; i < loop_size; ++i)
{
if (flavors[i] == cookieOrdered)
{
valid_option = true;
break;
}
}
Hint: lookup Case insensitive string comparison in C++

Using a virtually inherited function non-virtually?

I have run into trouble trying to implement functionality for serializing some classes in my game. I store some data in a raw text file and I want to be able to save and load to/from it.
The details of this, however, are irrelevant. The problem is that I am trying to make each object that is interesting for the save file to be able to serialize itself. For this I have defined an interface ISerializable, with purely virtual declarations of operator<< and operator>>.
The class Hierarchy looks something like this
-> GameObject -> Character -> Player ...
ISerializable -> Item -> Container ...
-> Room ...
This means there are many possible situations for serializing the objects of the different classes. Containers, for instance, should call operator<< on all contained items.
Now, since operator>> is virtual, i figured if I wanted to serialize something that implements the functionality defined in ISerializable i could just do something like
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
and then
ostream & Character::operator<<(ostream & os){
GameObject::operator<<(os);
os << character_specific_property 1 << " "
<< character_specific_property 2 << "...";
return os;
}
but I quickly learnt that this first attempt was illegal. What I'm asking here is how do I work around this?
I don't feel like implementing a function manually for each class. I guess I'm looking for something like the super functionality from Java.
Any help is appreciated.
-- COMMENTS ON EDIT ------------
Alright, last time I was in a hurry when I was writing the question. The code is now more like it was when I tried to compile it. I fixed the question and the problem I had was unrelated to the question asked. I'm ashamed to say it was caused by an error in the wake of a large refactoring of the code, and the fact that the operator was not implemented in every base class.
Many thanks for the replies however!
The problem is not in your attempt to call a virtual function non-virtually. The problem is this line: os = Character::operator<<(os);. That is an assignment, but std::ostream doesn't have an operator=.
You don't need the assignment anyway. The stream returned is the same stream as the stream you pass in. The only reason it's returned is so you can chain them.
Hence the fix is to just change the code to
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
This is not how overloading operator<< for ostream works. The left-hand operator is an ostream (hence you gotta overload it as a free function) and the right-hand operator is your object (which is why the virtual mechanism wouldn't easily work.
I suppose you could try:
class Base
{
//...
virtual std::ostream& output(std::ostream&) const;
};
std::ostream& operator<< (std::ostream& os, const Base& obj)
{
return obj.output(os);
}
Now a derived class naturally might call the output method of its parent(s):
class Derived: public Base
//...
virtual std::ostream& output(std::ostream& os) const
{
Base::output(os);
return os << my_specific_data;
}
};