I have a strange issue where ostringstream is empty even though I insert an output to it. Here is my code:
//logger.h
#include <string>
#include <iostream>
#include <sstream>
using std::string;
class BasicLogger {
public:
BasicLogger(const string name);
BasicLogger(const BasicLogger& basicLogger);
~BasicLogger();
template<class T>
BasicLogger& operator<<(const T &msg){
std::cout << "msg is: " << msg << std::endl;
mBuf << msg;
std::cout << "mBuf is: " << mBuf.str() << std::endl;
return *this;
}
private:
string mName;
std::ostringstream mBuf;
};
class Logger {
public:
Logger();
~Logger();
BasicLogger info();
BasicLogger error();
private:
BasicLogger mInfoLogger;
BasicLogger mErrorLogger;
};
//logger.cpp
#include "logger.h"
BasicLogger::BasicLogger(const string name):
mName(name) { }
BasicLogger::BasicLogger(const BasicLogger& otherLogger) {
this->mName = otherLogger.mName;
this->mBuf << otherLogger.mBuf.rdbuf();
}
BasicLogger::~BasicLogger() { }
Logger::Logger():
mInfoLogger("[INFO]"),
mErrorLogger("[ERROR]") {}
Logger::~Logger() {};
BasicLogger Logger::info() {
return mInfoLogger;
}
BasicLogger Logger::error() {
return mErrorLogger;
}
//main.cpp
#include "logger.h"
int main() {
Logger logger;
logger.info() << "Hellooo";
}
The output is
msg is: Hellooo
mBuf is:
While @BoPersson already gave you the solution, I would like to explain what happened here, and why your output is empty, even though you are adding to ostringstream
on the line just before you display its content.
I think when you attempted to return mInfoLogger
by value, the compiler complained about not being able to return it because copy constructor was deleted. The reason it was deleted because ostringstream
member you have is non-copyable.
So you provided custom copy constructor and attempted to copy the stream this way:
this->mBuf << otherLogger.mBuf.rdbuf();
Only this does not copy anything as your rdbuf
is empty and instead sets failbit
on
The failbit
The streambuf overload of basic_ostream::operator<< if the function inserts no characters. http://en.cppreference.com/w/cpp/io/ios_base/iostate
If you were to check your message insertion like this:
if (!(mBuf << msg))
std::cout << "Not Inserted" << std::endl;
You would see Not Inserted
message printed. There are many ways to make it print the desired message. For example making sure your rdbuf
buffer is not empty or by resetting the failbit
before you reuse the mBuf
, something like mBuf.clear();
or simply by returning the reference to mInfoLogger
(and mErrorLogger
). Then you can safely get rid of your copy constructor.