I have been looking for a solution but couldn't find what I need/want.
All I want to do is pass a stream intended for std::cout to a function, which manipulates it. What I have used so far is a template function:
template<typename T>
void printUpdate(T a){
std::cout << "blabla" << a << std::flush;
}
int main( int argc, char** argv ){
std::stringstream str;
str << " hello " << 1 + 4 << " goodbye";
printUpdate<>( str.str() );
return 0;
}
What I would prefer is something like:
printUpdate << " hello " << 1 + 4 << " goodbye";
or
std::cout << printUpdate << " hello " << 1 + 4 << " goodbye";
I was trying to do:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
but that gave me:
error: invalid operands of types ‘void(std::istream&) {aka void(std::basic_istream<char>&)}’ and ‘const char [5]’ to binary ‘operator<<’
You can't output data to an input stream, just not a good thing to do.
Change:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
To:
void printUpdate(std::ostream& a){
std::cout << "blabla" << a << std::flush;
}
Note the stream type change.
Edit 1:
Also, you can't output a stream to another stream, at least std::cout.
The return value of << a is a type ostream.
The cout stream doesn't like being fed another stream.
Change to:
void printUpdate(std::ostream& a)
{
static const std::string text = "blabla";
std::cout << text << std::flush;
a << text << std::flush;
}
Edit 2:
You need to pass a stream to a function requiring a stream.
You can't pass a string to a function requiring a stream.
Try this:
void printUpdate(std::ostream& out, const std::string& text)
{
std::cout << text << std::flush;
out << text << std::flush;
}
int main(void)
{
std::ofstream my_file("test.txt");
printUpdate(my_file, "Apples fall from trees.\n");
return 0;
}
Chaining Output Streams
If you want to chain things to the output stream, like results from functions, the functions either have to return a printable (streamable object) or the same output stream.
Example:
std::ostream& Fred(std::ostream& out, const std::string text)
{
out << "--Fred-- " << text;
return out;
}
int main(void)
{
std::cout << "Hello " << Fred("World!\n");
return 0;
}
Related
I'm sorry the title may be inaccurate.I'm new to C++.
Here is my code and output...
#include <iostream>
#include <sstream>
using namespace std;
class LogLine {
private:
stringstream ss;
string message;
public:
~LogLine() {
ss << "\n";
message = ss.str();
cout << message;
message = "";
}
template <class T>
LogLine& operator<<(const T& thing) {
ss<< thing;
return *this;
}
LogLine& operator<<(std::ostream &(*manip)(std::ostream &)) {
manip(ss);
return *this;
}
};
int main(int argc, char *argv[])
{
LogLine log;
cout<< "Line One"<<endl;
log << "I'm " << 25 << " years old...."<<endl;
cout<<"Line Two"<<endl;
log << "I " << "Live in " << " Houston....";
return 0;
}
Current output:
Line One
Line Two
I'm 25 years old....
I Live in Houston....
Desired output:
Line One
I'm 25 years old....
Line Two
I Live in Houston....
I hope in each line of "log" be able to detect the end of that line and print out current message, and then clean itself. I know the reason of current output, but I can't figure out how should I modify my code to get desired output.("endl" can be missing)
Thanks a lot for any comments.
As described above...
When I understand you correctly, you want to detect the end of the statement, where log is used, and then append a std::endl.
My solution is similar to that one of #MarekR, but it forces a line break, when log is not rebound:
It does not detect "\n" and flushes it to std::cout, that would be contra productive on parallel std::cout calls.
#include <iostream>
#include <sstream>
using std::cout;
using std::endl;
class LogLine {
std::stringstream ss;
public:
LogLine(LogLine&&) noexcept = default;
LogLine() = default;
~LogLine()
{
if(ss && ss.peek() != -1){
cout << ss.str() << std::endl;
}
}
template <class T>
friend LogLine operator<<(LogLine& lhs, const T& thing)
{
lhs.ss << thing;
return std::move(lhs);
}
template <class T>
friend LogLine&& operator<<(LogLine && lhs, const T& thing)
{
lhs.ss << thing;
return std::move(lhs);
}
LogLine&& operator<<(std::ostream& (*manip)(std::ostream&))
{
manip(ss);
return std::move(*this);
}
};
int main()
{
LogLine forced;
cout << "Line One" << endl;
forced << "I'm " << 25 << " years old....";
cout << "Line Two" << endl;
LogLine() << "I " << "Live in " << " Houston...." << endl << endl << endl;
forced << "forced 2";
std::cout << "End of the sausage" << std::endl;
return 0;
}
That what happens here is: every call to operator<< creates a temporary, which steals the resources of the original structure. Therefore, when it is not rebound, the destructor gets called directly after the line, flushing the stringstream.
So I am creating a class that inherits from ifstream, and that gives me acces to the protected function set_rdbuf, and at first I just thought it allowed you to set your own filebuf that then would be used, but that does not seem to work for me. I wrote the following code:
class A : public std::fstream {
private:
std::filebuf m_file_buf;
public:
A() {
if (!m_file_buf.open("test_file.txt", ios_base::out | ios_base::in)) {
std::cout << "something went wrong";
}
// std::fstream::rdbuf()->swap(m_file_buf);
std::fstream::set_rdbuf(&m_file_buf);
std::cout << "m_ file buff is: " << m_file_buf.is_open() << "\n";
std::cout << "rd file buff is: " << std::fstream::rdbuf()->is_open() << "\n";
std::cout << "we are: " << std::fstream::is_open() << "\n";
}
};
int main() {
A a;
return 0;
}
This will log:
m_ file buff is: 1
rd file buff is: 0
we are: 0
I was under the assumption that when I called rdbuf() I would then get the one I had set it to. However, if I use the swap function that rdbuf() provides, then it prints as I expect it to
class A : public std::fstream {
private:
std::filebuf* m_file_buf;
public:
A() {
m_file_buf = new std::filebuf();
if (!m_file_buf->open("test_file.txt", ios_base::out | ios_base::in)) {
std::cout << "something went wrong";
}
std::fstream::rdbuf()->swap(*m_file_buf);
std::cout << "m_ file buff is: " << m_file_buf->is_open() << "\n";
std::cout << "rd file buff is: " << std::fstream::rdbuf()->is_open() << "\n";
std::cout << "we are: " << std::fstream::is_open() << "\n";
// Get it back again as we swapped it out
m_file_buf = std::fstream::rdbuf();
}
};
int main() {
A a;
return 0;
}
m_ file buff is: 0
rd file buff is: 1
we are: 1
//and when I at the end swap back, everything is 1/open
I swited to pointer in the swap code so that I could point to the return of rdbuf()
This was compiled on MSVC version 19.28 with arg /std:c++17
So am I wrong is how set_rdbuf is supposed to be used, or is there something else I am doing wrong?
I would like to create a class for logging purposes which will behave like std::cout, but will automatically insert additional information to the stream.
a sample usage that I want would be something like (lets not care about object and context type for now, just assume they are std::string) :
Logger l;
l << "Event with object : " << obj << " while in context : " << context;
Then the output would be :
[timestamp] Event with object : [obj_desc] while in context : [this context][eol][flush]
I've been trying with :
template<typename T>
Logger& operator << (const T& msg){
std::cout << timestamp() << msg << std::endl << std::flush;
return *this;
}
but it seems that std::cout cannot resolve the typename T and fails to output a std::string for example while segfaulting.
A possible solution would be to overload this for all types, but this is rather annoying and time consuming.
Is there a better option to decorate std::cout output with more information?
Edit :
I do realize now that endl and flush will be appended to every message which kind of defeat the purpose, but I'm still interested in the general idea. I care more about the monadic syntax to append an arbitrary number of messages than the <<overload
The reason your code does not work is because you have not implemented operator<< for everything you want to pass to it.
This statement:
Logger l;
l << "Event with object : " << obj << " while in context : " << context;
Is basically doing this (assuming operator<< is a member of Logger, which your implementation implies it is):
Logger l;
l.operator<<("Event with object : ").operator<<(obj).operaator<<(" while in context : ").operator<<(context);
So, you need separate overloads of operator<< for string, obj, context, etc. And you need a way to indicate when to flush the complete log message to std::cout.
I would suggest something more like this:
struct LoggerStream
{
std::ostringstream strm;
struct Timestamp
{
};
~LoggerStream()
{
std::string s = strm.str();
if (!s.empty())
std::cout << s << std::flush;
}
LoggerStream& operator<< (const Timestamp &t)
{
strm << "[timestamp] "; // format this however you need
return *this;
}
LoggerStream& operator<< (const object &obj)
{
strm << "[obj_desc]"; // format this however you need
return *this;
}
LoggerStream& operator<< (const context &ctx)
{
strm << "[this context]"; // format this however you need
return *this;
}
LoggerStream& operator<< (std::ostream&(*f)(std::ostream&))
{
if (f == (std::basic_ostream<char>& (*)(std::basic_ostream<char>&)) &std::flush)
{
std::string s = strm.str();
if (!s.empty())
std::cout << s << std::flush;
strm.str("");
strm.clear();
}
else
strm << f;
return *this;
}
template<typename T>
LoggerStream& operator<< (const T& value)
{
strm << value;
return *this;
}
};
class Logger
{
LoggerStream getStream()
{
LoggerStream strm;
strm << Timestamp;
return strm;
}
};
Then you can do things like this:
Logger l;
l.getStream() << "Event with object : " << obj << " while in context : " << context;
...
l.getStream() << "Event with object : " << obj << " while in context : " << context;
...
Logger l;
LoggerStream strm = l.getStream();
strm << "Event with object : " << obj << " while in context : " << context << std::flush;
...
strm << Logger::Timestamp << "Event with object : " << obj << " while in context : " << context << std::flush;
...
Alternatively:
struct Logger
{
std::ostringstream strm;
~Logger()
{
std::string s = strm.str();
if (!s.empty())
std::cout << "[timestamp] " << s << std::flush;
}
Logger& operator<< (const object &obj)
{
strm << "[obj_desc]"; // format this however you need
return *this;
}
Logger& operator<< (const context &ctx)
{
strm << "[this context]"; // format this however you need
return *this;
}
Logger& operator<< (std::ostream&(*f)(std::ostream&))
{
if (f == (std::basic_ostream<char>& (*)(std::basic_ostream<char>&)) &std::flush)
{
std::string s = strm.str();
if (!s.empty())
std::cout << "[timestamp] " << s << std::flush;
strm.str("");
strm.clear();
}
else
strm << f;
return *this;
}
template<typename T>
Logger& operator<< (const T& value)
{
strm << value;
return *this;
}
};
Logger() << "Event with object : " << obj << " while in context : " << context;
...
Logger() << "Event with object : " << obj << " while in context : " << context;
...
Logger l;
l << "Event with object : " << obj << " while in context : " << context << std::flush;
...
l << "Event with object : " << obj << " while in context : " << context << std::flush;
...
You can certainly overload the stream classes if you want, providing operator<< for all the data types you want to support (and that's probably the "correct" way to go) but, if all you're after is a quick way to add logging to a regular stream, there a simpler way:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <ctime>
#include <unistd.h>
#define logcout std::cout << timestamp()
std::string timestamp(void) {
time_t now = time(0);
struct tm *tmx = localtime(&now);
std::ostringstream oss;
oss << '['
<< (tmx->tm_year+1900)
<< '-'
<< std::setfill('0') << std::setw(2) << (tmx->tm_mon+1)
<< '-'
<< std::setfill('0') << std::setw(2) << (tmx->tm_mday)
<< ' '
<< std::setfill('0') << std::setw(2) << (tmx->tm_hour)
<< ':'
<< std::setfill('0') << std::setw(2) << (tmx->tm_min)
<< ':'
<< std::setfill('0') << std::setw(2) << (tmx->tm_sec)
<< "] ";
return oss.str();
}
int main (int argc, char *argv[]) {
logcout << "A slightly\n";
sleep (5);
logcout << "sneaky" << " solution\n";
return 0;
}
which outputs:
[2015-05-26 13:37:04] A slightly
[2015-05-26 13:37:09] sneaky solution
Don't be fooled by the size of the code, I just provided a complete compilable sample for testing. The crux of the matter is the single line:
#define logcout std::cout << timestamp()
where you can then use logcout instead of std::cout, and every occurrence prefixes the stream contents with an arbitrary string (the timestamp in this case, which accounts for the bulk of the code).
It's not what I would call the most pure C++ code but, if your needs are basically what you stated, it'll certainly do the trick.
I just want to format a string and an integer value with right justify.
There is no problem to do this without leading space before the integer value.
bytes.....................123981
total bytes..............1030131
But it should look like this:
bytes ................... 123981
total bytes ............ 1030131
Unfortunately the example below wont work, because setw (right justify) relates only to the next stream element.
int iBytes = 123981;
int iTotalBytes = 1030131;
cout << setfill('.');
cout << right;
cout << "bytes " << setw(20) << " " << iBytes << endl;
cout << "total bytes " << setw(14) << " " << iTotalBytes << endl;
I hardly ever use std::cout, so is there a simple way to do this without previously joining a space char to the value?
The simplest way would be to write your " " and value into a std::stringstream and write the resulting str() into your output stream like:
std::stringstream ss;
ss << " " << iBytes;
cout << "bytes " << setw(20) << ss.str() << endl;
And here comes the complete overkill. A templated class prefixed which can be printed and bundles the two constructor arguments prefix,val into one string to be printed. number format, and precision is taken from the final output stream. Works with ints,floats, strings and const char *. And should work with every arg that has a valid output operator.
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
template<class T>
class prefixed_base {
public:
prefixed_base(const std::string & prefix,const T val) : _p(prefix),_t(val) {
}
protected:
std::string _p;
T _t;
};
// Specialization for const char *
template<>
class prefixed_base<const char*> {
public:
prefixed_base(const std::string & prefix,const char * val) : _p(prefix),_t(val) {
}
protected:
std::string _p;
std::string _t;
};
template<class T>
class prefixed : public prefixed_base<T> {
private:
typedef prefixed_base<T> super;
public:
prefixed(const std::string & prefix,const T val) : super(prefix,val) {
}
// Output the prefixed value to an ostream
// Write into a stringstream and copy most of the
// formats from os.
std::ostream & operator()(std::ostream & os) const {
std::stringstream ss;
// We 'inherit' all formats from the
// target stream except with. This Way we
// keep informations like hex,dec,fixed,precision
ss.copyfmt(os);
ss << std::setw(0);
ss << super::_p;
ss.copyfmt(os);
ss << std::setw(0);
ss << super::_t;
return os << ss.str();
}
};
// Output operator for class prefixed
template<class T>
std::ostream & operator<<(std::ostream & os,const prefixed<T> & p) {
return p(os);
}
// This function can be used directly for output like os << with_prefix(" ",33.3)
template<class T>
prefixed<T> with_prefix(const std::string & p,const T v) {
return prefixed<T>(p,v);
}
int main() {
int iBytes = 123981;
int iTotalBytes = 1030131;
cout << setfill('.');
cout << right;
cout << "bytes " << setw(20) << with_prefix(" ",iBytes) << endl;
cout << "total bytes " << setw(14) << with_prefix(" ",iTotalBytes) << endl;
cout << "bla#1 " << setw(20) << std::fixed << std::setprecision(9) << with_prefix(" ",220.55) << endl;
cout << "blablabla#2 " << setw(14) << std::hex << with_prefix(" ",iTotalBytes) << endl;
}
#Oncaphillis thx for the piece of source code, I adapt it a bit for my needs. I just wrote a function to convert values. std::to_string is used by C++11 standard, so I decided to use _to_string/_to_wstring instead. The tricky part was to get "wcout" to work with UNICODEs on Windows console. I didn’t really manage it, so I had to do a workaround. Anyway to print e.g. Cyrillic characters you have to change the console font to Consolas or Lucida.
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#if defined(UNICODE) || defined(_UNICODE)
#define _tcout std::wcout
#define _to_tstring _to_wstring
template <typename T>std::wstring _to_wstring(const T& value) {
std::wostringstream wos;
wos.copyfmt(std::wcout);
wos << value;
return wos.str();
}
#else
#define _tcout std::cout
#define _to_tstring _to_string
template <typename T> std::string _to_string(const T& value) {
std::ostringstream os;
os.copyfmt(std::cout);
os << value;
return os.str();
}
#endif
int _tmain(int argc, _TCHAR* argv[]) {
int iBytes = 123981;
int iTotalBytes = 1030131;
#if defined(UNICODE) || defined(_UNICODE)
wostringstream newCoutBuffer;
wstreambuf* oldCoutBuffer = _tcout.rdbuf(newCoutBuffer.rdbuf()); // redirect cout buffer
#endif
_tcout.imbue(std::locale("German")); // enable thousand separator
_tcout.precision(0);
_tcout << setfill(_T('.')) << right << fixed;
_tcout << _T("bytes ") << setw(20) << _T(" ") + _to_tstring(iBytes) << endl;
_tcout << _T("bytes total ") << setw(14) << _T(" ") + _to_tstring(iTotalBytes) << endl;
_tcout << _T("bla bla ") << fixed << setprecision(9); _tcout << setw(18) << _T(" ") + _to_tstring(0.1337) << endl;
_tcout << _T("Милые женщины ") << hex; _tcout << setw(12) << _T(" ") + _to_tstring(iTotalBytes) << endl;
_tcout << _T("retries ") << dec; _tcout << setw(18) << _T(" ") + _to_tstring(2) + _T(" of ") + _to_tstring(20) << endl;
#if defined(UNICODE) || defined(_UNICODE)
DWORD dwWritten;
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), newCoutBuffer.str().c_str(),newCoutBuffer.tellp(),&dwWritten,NULL);
_tcout.rdbuf(oldCoutBuffer);
#endif
return 0;
}
Output:
bytes ............ 123.981
bytes total .... 1.030.131
bla bla ...... 0,133700000
Милые женщины ..... fb.7f3
retries .......... 2 of 20
I want to have a function that outputs certain pieces of information to a specific designated source that is inputted to the function. In code, what I mean is:
function output( source ) {
source << "hello" << endl;
}
where source can be a ofstream or cout. So that I can call this function like so:
output(cout) or ofstream otp ("hello"); output(otp)
My question is, how do I characterize source to make this work? It's fair to assume that source will always be a member of the std class
Thanks!
void output(std::ostream &source) {
source << "hello" << std::endl;
}
or even:
template <T>
void output(T &source) {
source << "hello" << std::endl;
}
Write your function as:
std::ostream& output(std::ostream& source )
{
return source << "hello" << endl;
}
Then you can use it as:
output(cout);
//and
ofstream otp ("hello");
output(otp);
//and
output(output(cout));
output(output(output(cout)));
output(output(output(output(cout))));
//and even this:
output(output(output(output(cout)))) << "weird syntax" << "yes it is" ;
By the way, if the output function has many lines, then you can write it as:
std::ostream& output(std::ostream& source )
{
source << "hello" << endl;
source << "world" << endl;
//....
return source;
}
The point is that it should return source. In the earlier version, the function returns source.
You should pass an std::ostream& as argument
function output( source ) {
source << "hello" << endl;
}
If this is a member function, the point of which is to dump data about objects of the class of which it is a member, consider renaming it to operator<<. So, instead of
class Room {
...
// usage myRoom.output(otp)
void output(std::ostream& stream) {
stream << "[" << m_name << ", " << m_age << "]";
}
};
rather, try this:
class Room {
...
// usage opt << myRoom << "\n"
friend std::ostream& operator<<(std::ostream& stream, const Room& room) {
return stream << "[" << room.m_name << ", " << room.m_age << "]";
}
};
That way, you can display the state of your class using a more natural syntax:
std::cout << "My Room: " << myRoom << "\n";
instead of the klunky
std::cout << "My Room: ";
myRoom.output(std::cout);
std::cout << "\n";
IMHO, redirecting output should be done at the user level. Write your C++ like this:
cout << "hello" << endl;
And when executing the application, user can redirect the output to whatever he wants, say a file:
myapp > myfile