How would someone do that?
for example I do like:
std::cout << "something";
then it should print the time before "something"
Make your own stream for that :) This should work:
class TimedStream {
public:
template<typename T>
TimedStream& operator<<(const T& t) {
std::cout << getSomeFormattedTimeAsString() << t << std::endl;
return *this;
}
};
TimedStream timed_cout;
void func() {
timed_cout << "123";
}
You'd be able to use this class for every type for which std::cout << obj can be done, so no further work is needed.
But please note that the time will be written before every <<, so you cannot chain them easily. Another solution with explicit timestamp is:
class TimestampDummy {} timestamp;
ostream& operator<<(ostream& o, TimestampDummy& t) {
o << yourFancyFormattedTimestamp();
}
void func() {
cout << timestamp << "123 " << 456 << endl;
}
You could use a simple function that prints the timestamp and then returns the stream for further printing:
std::ostream& tcout() {
// Todo: get a timestamp in the desired format
return std::cout << timestamp << ": ";
}
You would then call this function instead of using std::cout directly, whenever you want a timestamp inserted:
tcout() << "Hello" << std::endl;
ostream& printTimeWithString(ostream& out, const string& value)
{
out << currentTime() << ' ' << value << std::endl;
return out;
}
Generate current time using your favourite Boost.DateTime output format.
This looks like homework. You want something in the line of:
std::cout << time << "something";
Find a way the retrieve the time on your system, using a system call.
Then you'll have to implement a << operator for your system-dependent time class/struct.
Related
I'm trying to write a simple logging function which can handle different types in this format:
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
I've been looking at the examples here:
How to use my logging class like a std C++ stream?
stringstream with recursive variadic function?
and this is what I came up with:
#include <iostream>
#include <sstream>
void LOG(std::stringstream& ss)
{
std::cout << ss.str() << std::endl;
}
However, even when I just do:
LOG("Some text");
I get the error:
could not convert ‘(const char*)"Some text"’ from ‘const char*’ to ‘std::stringstream’ {aka ‘std::__cxx11::basic_stringstream<char>’}
How can I implement this?
A common way to solve this is to make LOG a macro that just does text substitution instead. You could define a LOG macro like
#define LOG(to_log) \
do \
{ \
std::cout << to_log << std::endl; \
} while (false)
and then
LOG("This is one type: " << one_type << " and here is a different type: " << diff_type);
would get expanded to
do
{
std::cout << "This is one type: " << one_type << " and here is a different type: " << diff_type << std::endl;
} while (false);
template <typename ... T>
void log(T const& ... t)
{
( std::cout << ... << t );
// maybe want to add a newline?
std::cout << std::endl; // note: '\n' just adds it,
// std::endl flushes the stream...
}
would allow to log (to console!) as:
log("this is an int: ", 1210, " and this is a double: ", 10.12);
Note the commas instead of the stream operator (<<)...
If you want to log to arbitrary streams you might need to add it as yet another parameter (/*...*/ void log(std::ostream& s, T const&... t)) or you might (among other solutions) initialise some singleton that you access from within the logging function:
void initialiseLogging(std::ostream& s)
{
Logger::instance().initialize(s);
}
template <typename ... T>
void log(T const& ... t)
{
// assumes returning a reference:
( Logger::instance().stream() << ... << t );
}
Above variant assumes initialisation being required and logging without yielding undefined behaviour (needs to be documented!). If you want to be able to log without you need to change:
{
// now assuming a pointer being returned!
auto s = Logger::instance().stream();
// variant 1: log to nowhere if not initialised:
if(s)
{
( *s << ... << t );
}
// variant 2: default logging to console
s = s ? s : &std::cout;
( *s << ... << t );
}
I have some C++ console programs that display progress information on the last line of output, at regular intervals.
This progress line is cleared prior to writing the next real output (or updated progress information); this could be from a number of different places in the source, and I'm currently clearing the progress line on each one, e.g.:
cout << clearline << "Some real output" << endl;
...
cout << clearline << "Some other real output" << endl;
...
cout << clearline << setw(4) << ++icount << ") " << ... << endl;
...
cout << clearline << "Progress info number " << ++iprog << flush;
Here, 'clearline' is some (system dependent) string like "\r\33[2K" which clears the current last line.
I would prefer something cleaner, that localises source changes to the actual line that's going to be cleared, like simply:
cout << "Progress info number " << ++iprog << flush << defer_clearline;
where 'defer_clearline' causes the writing of 'clearline' to be deferred until just prior to the next cout output, wherever and whatever that happens to be. I then wouldn't need to use 'clearline' on all the other lines.
I thought it might be possible to do this if 'defer_clearline' is a manipulator, and/or using xalloc() and iword().
But I've not managed to get anything that works.
Is it possible to do this sort of thing, and if so how?
2020-12-30: edited to include missing 'flush's.
You can pretty easily setup an std::cout wrapper:
// Declare the empty struct clear_line and instantiate the object cls
struct clear_line { } cls;
class out {
private:
std::ostream &strm = std::cout;
bool is_next_clear = false;
public:
template <typename T>
out& operator<<(const T& obj) {
if(is_next_clear) {
strm << std::endl << std::endl << std::endl; // clear logic
is_next_clear = false;
}
strm << obj;
return *this;
}
out& operator<<(const clear_line& _) {
is_next_clear = true;
return *this;
}
};
This pretty simply stores an is_next_clear bool for whether or not the next regular output should be cleared. Then, in the general case (the templated operator<<()), we run your clear logic and flip the is_next_clear flag if applicable. Then just output as usual.
Then, the operator<<() is overloaded for the case of a clear_line object. So if one of those is sent, we know to flip the is_next_clear flag, but not actually output anything.
Here's an example use:
int main() {
out o;
o << "Some real output" << cls;
o << "Some other real output";
return 0;
}
Here it is in action: https://ideone.com/0Dzwlv
If you want to use endl, you'll need to add a special overload for it as this answer suggests: https://stackoverflow.com/a/1134467/2602718
// this is the type of std::cout
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);
// define an operator<< to take in std::endl
out& operator<<(StandardEndLine manip)
{
// call the function, but we cannot return its value
manip(strm);
return *this;
}
Live example: https://ideone.com/ACUMOo
I have a method to log with the following definition:
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
I'm trying to call this method like this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
direction and count are integers.
I'm getting this following error with << underlined in red:
no operator << matches these operands.
operand types are const char [10] << std::string
I have #include<string> in my header to make sure my strings are working as they should.
I tried std::string("direction") and still the issue was same.
Beginner in C++. Help would be appreciated.
operator<< isn't used for arbitrary string concatenation - it is called an "output stream operator", and it is only used in the context of std::ostream.
When you say...
std::cout << tag << " :" << s << std::endl;
...you're actually writing code roughly equivalent to:
std::cout.operator<<(tag).operator<<(" :").operator<<(s).operator<<(std::endl);
As you can see operator<< knows how to work with std::cout and std::string, but not between strings.
In order to concatenate std::string instances, you can simply use operator+:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
Please note that this concatenation technique is not the most efficient: you might want to look into std::stringstream or simply use std::string::reserve to avoid unnecessary memory allocations.
Substitute the << with the + operator as you are manipulating the string, not the stream:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
If you're determined to use the operator<< notation you need an object that understands it.
Here's such an object (I make no claims that this is a good idea):
#include <string>
#include <sstream>
#include <iostream>
void log(std::string s) {
std::string tag = "main";
std::cout << tag << " :" << s << std::endl;
}
struct string_accumulator
{
std::ostringstream ss;
template<class T>
friend string_accumulator& operator<<(string_accumulator& sa, T const& value)
{
sa.ss << value;
return sa;
}
template<class T>
friend string_accumulator& operator<<(string_accumulator&& sa, T const& value)
{
return operator<<(sa, value);
}
operator std::string () { return ss.str(); }
};
inline auto collect() -> string_accumulator
{
return string_accumulator();
}
int main()
{
int direction = 1;
int count = 1;
log(collect() << "direction" << std::to_string(direction) << ", count: " << std::to_string(count));
}
The prototype of your function is void log(std::string s);. It awaits for an std::string. So you need to pass a string to it, not a stream!
So, change this:
log("direction" << std::to_string(direction) << ", count: " << std::to_string(count));
to this:
log("direction" + std::to_string(direction) + ", count: " + std::to_string(count));
where I only changed the << operator to + operator. It will now concatenate everything inside the parentheses to a single std::string.
Your attempt implies that you wanted to pass std::ostream as the parameter. Maybe you want to read C++ Passing ostream as parameter. However, if I were you, I would just overload <<.
why don't you use:
// just include thisusing namespace std;
I'm tired of making up on the spot debug codes and including <iostream> in every single file. So I wanted to make myself a universal, self-contained and lightweight debug class, that I would just include in the header, and forget.
I want to use something along the lines of
#include "debug.hpp"
debug DBG;
DBG << "foo and" << " bar";
//Or even better, just include it and do debug() << "foo and" << " bar";
So, I wrote this:
#include <iostream>
#include <string>
#include <chrono>
#include <ctime>
class Debug
{
public:
Debug &operator<<(std::string arg_0)
{
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
auto timeString(ctime(&tempTime));
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString << " >> " << arg_0 << '\n';
return *this;
}
};
But of course, this doesn't work because, as I've learned, every overload operator causes this function (is it still called a function?) to trigger separately. Creating:
hour:minute:second >> foo and
hour:minute:second >> bar
Any way I could pass everything at once after the first overload operator appears? Maybe as a stringstream? Also, I won't be only passing strings, but anything that I need, will this require me to manually create a separate overload function for every signle type that I may pass?
P.S: Cross-plaform solution is optional, but welcome (Currently developing on Linux)
You may return an other class to do the job, something like:
class Helper
{
public:
~Helper() { std::cout << "\n"; }
template<typename T>
friend Helper&& operator << (Helper&&h, const T& t) {
std::cout << t;
return std::move(h);
}
};
class Debug
{
public:
template<typename T>
friend Helper operator<<(Debug&, const T& t)
{
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
auto timeString{ctime(&tempTime)};
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString << " >> " << t;
return Helper{};
}
};
Each time you call operator<<, your code prints the time stamp and \n. And that's the problem. To avoid that, you can print the time stamp in the constructor of Debug, and print \n in the destructor.
class Debug {
public:
Debug() {
auto tempTime = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now() );
std::string timeString(ctime(&tempTime));
timeString = timeString.substr(timeString.find(':') - 2, 8);
std::cout << timeString;
}
~Debug() {
std::cout << "\n";
}
Debug &operator<<(std::string arg_0) {
std::cout << " >> " << arg_0;
return *this;
}
};
In order to debug types other than string, you make operator<< a template:
template <typename T>
Debug &operator<<(T &&arg_0) {
std::cout << " >> " << std::forward<T>(arg_0);
return *this;
}
I see 2 design problems here:
You try to create stream-like object. It means that it doesn't know, when the line ends, until you send EOL to it. Without this information, it doesn't know when to add prefix to "your" line and print it. Consider the two following situation:
DBG << "foo and" << " bar";
and
DBG << "foo and";
... (a lot of code) ...
DBG << " bar";
They look exactly the same inside your Debug class, because:
DBG << "foo and" << " bar"; == (DBG.operator<<("foo and")).operator<<(" bar");
And this is the same as:
DBG.operator<<("foo and");
DBG.operator<<("bar");
So you have to decide how to define the end of the message you want to print (and when do you want to measure the time: At the beginning or at the end of the message?).
When do you want to flush your stream? You have to send std::endl or std::flush to std::cout to flush it. Sending "\n" does not flush std::cout (this is important difference between std::endl and "\n"). If you do not flush it, it may be printed several minutes/hours later (it will wait in a buffer). On the other hand frequent buffer flushing may be a performance killer in application producing large amount of text.
Try to define how your stream should behave when you send to it "\n", std::endl and std::flush (std::endl should be converted to "\n"+std::flush).
About other questions:
I would use simple template to "transfer" parameter of operator<<() to std::cout. It would allow to use your class for any type that can be printed by std::cout. To make things simpler you can define the operator<<() outside your class, eg.:
template<typename tParam>
Debug &operator<<(Debug& stream, tParam const & myParam)
{
...
return stream;
}
How can I (in an external function) differentiate between cout << thingToShow and outfile << thingToWrite with different formats?
I have a single file that I am supposed to build all this implementation around without changing anything, and there are instances of
cout << "\nx matrix is: \n";
cout << x;
cout << "\ny matrix is: \n";
cout << y;
which are supposed to be formatted as
x matrix is:
--- ---
| 30 50 |
| |
| 25 40 |
--- ---
y matrix is:
--- ---
| 2 3 |
| |
| 1 1 |
--- ---
and I have instance of
w = r * w;
outfile << w;
which are supposed to be formatted simply as
-20 40
-80 60
my implementation is
ostream& operator<< (ostream &out, const Matrix& y){
out << "\t\t" << " ---\t\t\t\t ---\n"<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n\t\t|\t\t\t\t\t|\n\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n" << "\t\t" << " ---\t\t\t\t ---\n\n";
return out;
}
which works for the standard cout << thingToShow output format, but obviously messes up the outfile << thingToWrite format.
is there a property of the (stream &out,) argument I can put in an if statement? or is there some other way to differentiate between cout and outfile?
You can test if your ostream is cout:
if (&out == &std::cout)
And you can take the appropriate action, depending upon the result. But if you want my unsolicited opinion, I think it would be better to let the user decide how it prints out, using some kind of formatting class:
std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);
In this example, format would be a function which returns an object of some class which holds a Matrix object (by reference), and formatting options. This class would have its operator<< overloaded to produce the appropriate output to the stream based on the options that were given to it. Alternatively, you could make your own specialized i/o manipulators.
Not quite as easy as I thought.
It can be done by overloading std::ifstream. That means you have to overload it for all types so a catch-all template overload is needed in addition to your Matrix overload.
struct Matrix
{
int a, b;
};
// Matrix for std::cout
std::ostream& operator<<(std::ostream& os, const Matrix& t)
{
os << "[\n\t" << t.a << "\n\t" << t.b << "\n]";
return os;
}
// overload of general types for files
template<typename Type>
std::ofstream& operator<<(std::ofstream& ofs, const Type& t)
{
// this cast prevents infinite recursion
static_cast<std::ostream&>(ofs) << t;
return ofs;
}
// Matrix overload for files
std::ofstream& operator<<(std::ofstream& ofs, const Matrix& t)
{
// this cast prevents infinite recursion
static_cast<std::ostream&>(ofs) << "{" << t.a << ", " << t.b << "}";
return ofs;
}
int main()
{
std::ofstream ofs("test.txt");
Matrix m {3, 7};
std::cout << 4 << m << 9 << '\n';
ofs << 4 << m << 9 << '\n';
}
Output: std::cout
4[
3
7
]9
Output: ofs
4{3, 7}9
NOTE: This approach distinguishes between std::ofstream and its parent class std::ostream. This means you have to pass your std::ifstream explicitly typed to any functions if you want this behaviour to be available within the function.
You need to maintain some short of state to decide whether the output is going to be in short format or the long format. The best place to maintain that data is, I think, in the class Matrix itself.
Then, provide functions that can be used to set the format. You can also provide an overloaded operator<< function so you can use them with an ostream.
Here's a working version.
#include <iostream>
struct Matrix
{
int tl;
int tr;
int bl;
int br;
static void setLongFormat();
static void setShortFormat();
enum OutputFormat
{
LONG_FROMAT,
SHORT_FORMAT
};
static OutputFormat outputFormat;
};
Matrix::OutputFormat Matrix::outputFormat = Matrix::SHORT_FORMAT;
void Matrix::setLongFormat()
{
outputFormat = LONG_FROMAT;
}
void Matrix::setShortFormat()
{
outputFormat = SHORT_FORMAT;
}
std::ostream& operator<< (std::ostream &out, const Matrix& y)
{
if ( Matrix::outputFormat == Matrix::LONG_FROMAT )
{
out << "\t\t" << " ---\t\t\t\t ---\n"
<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n"
<< "\t\t|\t\t\t\t\t|\n"
<< "\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n"
<< "\t\t" << " ---\t\t\t\t ---\n\n";
}
else
{
out << y.tl<< "\t" << y.tr<< "\n"
<< y.bl<< "\t" << y.br<< "\n";
}
return out;
}
std::ostream& operator<<(std::ostream &out, void (*fun)())
{
fun();
return out;
}
int main()
{
Matrix a{30, 50, 25, 40};
std::cout << Matrix::setLongFormat << a << std::endl;
std::cout << Matrix::setShortFormat << a << std::endl;
};
Output:
--- ---
| 30 50 |
| |
| 25 40 |
--- ---
30 50
25 40
PS. The tabs don't look quite right here. I am sure the function can be modified to keep the tabs in their correct location.