I have a custom output class that has two std::ostream members that serve different purposes. Either stream is used depending upon how the output class is configured. In some instances, the two streams are chained together. A grossly simplified version of the class is below. I can provide some more details if needed.
class c_Output
{
public:
c_Output (bool x_useA) : m_useA(x_useA) { /* setup m_stream[AB] here */ };
~c_Output ();
inline std::ostream& stream () { return (m_useA ? m_streamA : m_streamB); };
private:
bool m_useA;
std::ostream m_streamA;
std::ostream m_streamB;
}
I know how to write stream operators for classes that I wish to stream to/from std::cout, std::cin, or any other std::iostream, but I am struggling to write stream operators where a c_Output instance serves as the lhs instead of a std::ostream instance.
Right now, I am able to get away with:
c_Output l_output;
uint64_t l_value = 0xc001c0de;
l_output.stream() << std::hex << std::setw(16) << std::setfill('0') << l_value;
c_Output::stream() returns the appropriate std::ostream&, so this behaves just as expected.
I would like to rewrite the above as:
c_Output l_output;
uint64_t l_value = 0xc001c0de;
l_output << std::hex << std::setw(16) << std::setfill('0') << l_value;
I have attempted several different versions of defining operator<< based on examples I have seen here on StackOverflow and the greater web to no avail. The latest version looks like this:
// in header
class c_Output
{
...
friend c_Output& operator<< (c_Output& x_output, std::ostream& x_stream);
...
}
// in source
c_Output&
operator<< (c_Output& x_output, std::ostream& x_stream)
{
x_output.stream() << x_stream;
return x_output;
}
The setup of the arguments is intended to mirror the standard stream operator overload. This setup gives me compile issues such as:
error: no match for 'operator<<' in 'l_output << std::hex'
note: candidates are: c_Output& operator<<(c_Output&, std::ostream&)
I have stripped away all the file and line information, but it gets the point across. I am obviously getting the type for the rhs of the operator incorrect. What is the correct type and/or correct means of implementing the stream operator as desired?
There is also a complementary c_Input class that has a similar requirement, but adapting the answer for c_Output should be trivial.
The type of std::hex is std::ios_base& (*)(std::ios_base&). Change your operator signature to:
c_Output& operator<< (c_Output& x_output, std::ios_base& (*x_stream)(std::ios_base&));
operator<< (c_Output& x_output, std::ostream& x_stream)
The only real problem is that std::hex isn't a std::ostream, and with your methods no overloaded << is available for it.
In order to support the usage of the hex modifier, you'll need another friend overload with parameters (c_Output&, ios_base& (*)(ios_base&)) (as hex is a pointer to function taking reference to ios_base returning reference to ios_base).
At the rate you're going, you'll need to also implement all the other << overloads as well. This is not a trivial task, but is necessary to masquerade as a std::ostream, with or without inheriting from it.
Related
I am looking for a way to use an ostream with my custom string class and overload the operator << to stream to the buffer which i can then flush to anywhere i want (in my case its just gonna be printed in a window)
I'm reasonably new to the inner workings of iostream's but from my understanding the method i've seen of making std::stringbuf a base of my custom stringstream would not work because the stringbuf deals with the std::string.
in essence i want to able to do this (or similar):
MyStringClass string
MyOutput << "hello" << string << "World" << std::endl;
Where MyOutput can be changed to print to anywhere i want.
Thank you.
Not a problem. Define your class, and within it's definition add an ostream& operator<<(const String&);.
Inside that operator, you can code whatever handling you want (look at std::string for inspiration)
I feel there should be a single liner with boost::phoenix that would let me stream an object having a member function ...::stream_to(std::ostream&) with << syntax. Something like this:
struct x { void stream_to(std::ostream&); }
LOG_INFO << MAGIC_SOMETHING(x);
But struggling to find that MAGIC_SOMETHING(...). Am specifically interested in a solution that won't require me doing a forwarding marker struct and ostream operator for it.
We have a log implementation that's based on std::ostream with a custom stream buffer. We implement our application's instance of the log class via a Schwarz counter.
To avoid coupling our lower level classes to our log implementation, we can pass a reference to a std::ostream. In this way our lower level classes can log to std::cout, std::cerr or to the instance created via the Schwarz counter.
I have one problem with this. The log implementation sets its severity via an overload of the stream operator:
// Overload the << operator to set the log message severity
inline CLogStream& operator << (CLogStream& myLogStream, eMsgType::type msgTypeCurrent)
{
myLogStream.SetMsgTypeCurrent(msgTypeCurrent);
return ( myLogStream ) ;
}
This allows us to use the logger like this:
CLog::Main << CLog::MSG_FATAL << "Fatal error" << std::endl;
I'd like to create a reference to our app's instance of the log which is locked to a particular severity. That way, I can pass our utility classes two std::ostream references. One of these would be used for normal reporting and the other for error reporting. These could be set to std::cout and std::cerr, or to some kind of object referring to our log object instance.
Unfortunately the std::ostream operator << aren't virtual as far as I'm aware, so I'm not sure how to design such an object.
Any thoughts?
iostream has virtual member functions (specifically, ~ios_base) so you can perform a dynamic_cast in the operator<<:
inline std::ostream &operator<<(std::ostream &os, eMsgType::type msgTypeCurrent) {
if (CLogStream *myLogStream = dynamic_cast<CLogStream *>(&os)) {
myLogStream->SetMsgTypeCurrent(msgTypeCurrent);
} else {
os << "TYPE: " << static_cast<typename std::underlying_type<eMsgType::type>
::type>(msgTypeCurrent) << ": ";
}
return os;
}
If the setting of the severity is persistent, such that both tese lines result in a log entry with fatal severity
CLog::Main << CLog::MSG_FATAL << "Log entry 1: " << some_data << std::endl;
CLog::Main << "Log entry 2: " << some_other_data << std::endl;
then your logging class is already correctly designed to be passed along as a generic ostream&. You just need separate logger instances for the different log-levels that are supported by the utility classes.
This is written under the assumption that the logger class has been inherited from ostream to take advantage of the existing operator<< overloads.
In that case, the operator<< for some_data and some_other_data are already completely unaware that the output goes to a log stream.
Read about ios_base::iword(). It gives you access to an array of long values in the stream object that you can use to store things like flags and special values.
I have to extend the ofstream class to write a logging stream service.
The goal is to intercept each line, adding at the head of each one a customized text (date/time, severity, and so on).
Now, it's clear that I'm not a C++ guru, so I read a lot of documentation about this task, e.g.
http://www.angelikalanger.com/Articles/Topics.html#CPP
http://asmodehn.wordpress.com/2010/06/20/busy-c-coding-and-testing
http://gabisoft.free.fr/articles-en.html
The above articles suggest to write a custom stream buffer, but during porting of this concept on file streams I encountered a lot of difficulties.
Is there a simpler method to achieve this goal?
You don't need to write a custom stream buffer; the simplest and most straightforward way is to make a class you can send output to by giving it a templatized single argument operator<<():
template <typename T>
std::ostream& operator<<(const T& data_)
{
m_outstream << m_severity << "\t" << getTimeStamp() << "\t" << data_;
return m_outstream;
}
Where m_outstream is some type of std::ostream (std::ofstream, etc). m_severity and getTimeStamp() are examples of what you can insert (and you can create a bog standard two argument operator<<() to format and output the severity type to an ostream).
This then allows you to do things like:
myLogger << "failingFunction(" << argument <<
"): Could not do something." << std::endl;
and you will get output on m_outstream that looks like:
WARNING 2012-01-03 19:32 failingFunction("argument value"): Could not do something.
Beyond this, you will want a way to set the severity, which can be as simple as a method called on the logger class you added the templatized operator<<() to. If you want to get really fancy, you can write your own manipulator that acts much like setw() would on a std::ostream. See http://www.math.hkbu.edu.hk/parallel/pgi/doc/pgC++_lib/stdlibug/man_6665.htm for a primer on writing manipulators.
Is it possible to define a second insertion operator to have two modes of outputting a class? Say e.g. one that outputs all members and one that just outputs some basic unique identifier that is grep-able in a log? If so, is there an operator that is usually chosen? I would guess as analogy to << one might use <<< if that is legal?
Thanks
If you want to output only the id, then the best idea is probably to provide a method to get the id in a type that's streamable (e.g. std::string id() const;). That's much more intuitive to other people working on the code than some strange operator use.
Your suggestion of <<< (it's not possible to create new operators in C++, but ignoring that for a moment) reveals that you're happy for there to be different code at the point of call. Therefore, the only benefit you'd get would be the saving of a few character's source code; it isn't worth the obfuscation.
By way of contrast, there are situations where you want the same streaming notation to invoke different behaviours, such as switching between id-only and full data, or different representations such as tag/value, CSV, XML, and binary. These alternatives are usually best communicated by either:
using different stream types (e.g. XMLStream rather than std::ostream), and defining XMLStream& operator<<(XMLStream&, const My_Type&) etc, and/or
using stream manipulators - you can create your own - random Google result: http://www.informit.com/articles/article.aspx?p=171014&seqNum=2
There's no such thing already defined or in use by convention.
Also, you cannot define your own operators in C++, you have to use one of the ones already in the language and overloadable, and <<< isn't an operator in C++, so it is out anyway.
I'd strongly recommend you don't use some other operator for this. (See rule #1 here for a more thorough explanation.) If you have subtle differences between output operations, well-chosen functions names go a long way for making better code than unclear operators arbitrarily picked.
No. You can't define your own operators (<<< doesn't exist in C++). But you can define a id() method returning a string and output this.
There is no such operator as <<< in C++.
You are, however, free to implement, for example operator <(ostream&,Object&), which would do what you want. The problem is, code may get unreadable when you try to chain < and << together.
you can use operator | for instance. Another way of doing this is to define small tag classes for which the operator is overloaded; example (pretty simplistic but you get the point):
template< class T >
struct GrepTag
{
GrepTag( const T& );
T value;
}
template< class T >
Greptag< T > MakeGrepTag( const T& x )
{
return GrepTag< T >( x );
}
template< class T >
MyClass& MyClass::operator << ( const GrepTag< T >& g )
{
//output g.value here
}
MyClass() << MakeGrepTag( "text" );
Yet another way, more like the standard streams, is to use a tag as well but keep some state internally:
struct GrepTag
{
}
MyClass& MyClass::operator << ( const GrepTag& g )
{
grepState = true;
}
template< class T >
MyClass& MyClass::operator << ( const T& )
{
if( grepState )
{
//output special
grepState = false;
}
else
{
//output normal
}
}
MyClass() << GrepTag() << "text";
You cannot define your own operators in C++. You can only overload those that exist.
So I recomend not using an operator for outputting basic unique identifier grep-able in a log. This doesn't correspond to any existing operator role. Use a method instead, such as exportToLog().