I'm currently writing a class to wrap stringstream. My overall goal is to provide a threadsafe << (ostream) for my stringstream. I'm having trouble figuring out the correct syntax of what I'm trying to do. Any help would be most appreciative!
Below you'll find what I've tried. I know this is not the correct syntax, but it is kind of what I'm shooting for. I could of course not overload the << operator and force users to use the AddValue, but that wouldn't be ideal for quick and easy string manipulation while writing the code.
class WrappedStringStream
{
public :
WrappedStringStream() ;
template<typename T>
void AddValue( const T & value )
{
m_mutex.Lock() ;
//here I'd like to do something like m_stringstream << value, but of course since
//I'm overloading operator<< that won't work
m_mutex.Unlock() ;
}
friend std::ostream & operator<<( std::ostream & out, const WrappedStringStream & string )
{
string.AddValue( out ) ;
return out ;
}
protected :
std::stringstream m_stringstream ;
mutable Mutex m_mutex ;
}
As mentioned above it doesn't compile, which I understand since I'm passing WrappedStringStream as a const parameter and calling AddValue which isn't const - resulting in the discards qualifier error.
Here is the solution
#include <iostream>
#include <sstream>
#include <mutex>
using namespace std;
class MutexWrapper
{
private:
mutex& m_mutex;
public:
MutexWrapper(mutex& mtx) : m_mutex(mtx) { mtx.lock () ; };
~MutexWrapper() { m_mutex.unlock () ; };
};
class WrappedStringStream
{
public :
WrappedStringStream() { };
template<typename T>
std::ostream & operator<<(const T& value)
{
MutexWrapper wrapper(m_mutex);
return m_stringstream << value;
}
void showStream()
{
cout << m_stringstream.str();
}
protected :
stringstream m_stringstream;
mutable mutex m_mutex ;
};
int main()
{
WrappedStringStream ws;
ws << "This is a string, " << 5 << 6.78;
ws.showStream();
return 0;
}
Output
This is a string, 56.78
======== edit ==========
Originally I was not quiet understand what the questioner's final goal, but just focus on how to fix his syntax issue.It is not a good idea to use << in a multithreading environment. We have a Log class, and in our log class we only have a Log method which takes variable amount of parameters. That will solve the problem.
Still, there is a solution for using << to lock the thread, but really urgly and NOT recommend. Downside is obvious - if you forgot to add the 'LoggingStart' and 'LoggingEnd', you might caught deadlock.
Also thanks #RemyLebeau, It should return *this instead of m_stringstream.
Please see code below.
#include <iostream>
#include <sstream>
#include <mutex>
using namespace std;
class WrappedStringStream
{
public:
enum StreamSignals
{
LoggingStart,
LoggingEnd
};
WrappedStringStream() { };
std::ostream & operator<<(const StreamSignals& signal)
{
if (signal == LoggingStart)
m_mutex.lock();
else if (signal == LoggingEnd)
m_mutex.unlock();
return *this;
}
template<typename T>
std::ostream & operator<<(const T& value)
{
m_stringstream << value;
return *this;
}
void showStream()
{
cout << m_stringstream.str();
}
protected :
stringstream m_stringstream;
mutable mutex m_mutex ;
};
int main()
{
WrappedStringStream ws;
ws << WrappedStringStream::StreamSignals::LoggingStart;
ws << "This is a string, " << 5 << 6.78;
ws << WrappedStringStream::StreamSignals::LoggingEnd;
ws.showStream();
return 0;
}
Related
Given some type that is streamable:
struct X {
int i;
friend std::ostream& operator<<(std::ostream& os, X const& x) {
return os << "X(" << x.i << ')';
}
};
I want to append this onto a std::string. I can implement this as:
void append(std::string& s, X const& x) {
std::ostringstream os;
os << x;
s.append(os.str());
}
But this seems lame since I'm writing data into one stream just to then allocate a new string just for the purposes of appending it onto a different one. Is there a more direct route?
This can be solved by a new type of streambuf (see Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference).
Here is a sketch of how it can look:
#include <streambuf>
class existing_string_buf : public std::streambuf
{
public:
// Store a pointer to to_append.
explicit existing_string_buf(std::string &to_append);
virtual int_type overflow (int_type c) {
// Push here to the string to_append.
}
};
Once you flesh out the details here, you could use it as follows:
#include <iostream>
std::string s;
// Create a streambuf of the string s
existing_string_buf b(s);
// Create an ostream with the streambuf
std::ostream o(&b);
Now you just write to o, and the result should appear as appended to s.
// This will append to s
o << 22;
Edit
As #rustyx correctly notes, overriding xsputn is required for improving performance.
Full Example
The following prints 22:
#include <streambuf>
#include <string>
#include <ostream>
#include <iostream>
class existing_string_buf : public std::streambuf
{
public:
// Somehow store a pointer to to_append.
explicit existing_string_buf(std::string &to_append) :
m_to_append(&to_append){}
virtual int_type overflow (int_type c) {
if (c != EOF) {
m_to_append->push_back(c);
}
return c;
}
virtual std::streamsize xsputn (const char* s, std::streamsize n) {
m_to_append->insert(m_to_append->end(), s, s + n);
return n;
}
private:
std::string *m_to_append;
};
int main()
{
std::string s;
existing_string_buf b(s);
std::ostream o(&b);
o << 22;
std::cout << s << std::endl;
}
You could write a std::string casting operator:
struct X {
int i;
friend std::ostream& operator<<(std::ostream& os, X const& x) {
os << "X(" << x.i << ')';
return os;
}
operator std::string() {
return std::string("X(") + std::to_string(x.i) + ")";
}
};
Then, you could simply append it to a std::string:
X myX;
myX.i = 2;
std::string s("The value is ");
s.append(myX); //myX is cast into the string "X(2)"
In this specific case I'd just follow the KISS principle:
struct X {
int i;
std::string toString() const {
return "X(" + std::to_string(i) + ")";
}
};
Usage:
string += x.toString();
std::cout << x.toString();
An operator<<(std::ostream&, …) isn't really suitable for generic string conversion, so if that's what you're after then a toString type of method / free function is much better. And if you want std::cout << x you can trivially implement operator<< to just call toString.
Since the original string is likely only large enough for the existing allocation, the best you can hope for is to format everything you want to append once in the stream, then append the result as you have in your example.
If you plan on performing these appends often, I would argue std::string is the wrong type for the problem at hand. I would recommend using an std::ostringtream directly instead of a std::string, and only convert to a string when you need the final result.
I'm making a simple logging class with a pointer to either a std::ofstream or std::cerr.
Is there any simple way to use a smart pointer for auto clean-up regardless of which stream is used?
The code must compile on clang++, g++, and VS2013.
Code
#include <iostream>
#include <fstream>
#include <string>
class Logger {
private:
std::ostream * output_stream{ nullptr };
bool using_file{ false };
public:
Logger()
{
output_stream = &std::cerr;
using_file = false;
}
Logger(std::string file)
{
output_stream = new std::ofstream(file);
using_file = true;
}
~Logger()
{
if (using_file)
{
delete output_stream;
}
}
template<typename T>
void log(T info)
{
*output_stream << info << std::endl;
}
};
class tmp {
int i{ 4 };
friend std::ostream & operator<<(std::ostream &os, const tmp& p);
};
std::ostream &operator<<(std::ostream &os, const tmp& p)
{
return os << p.i;
}
int main()
{
tmp t;
Logger logger;
logger.log(t);
system("pause");
return 0;
}
Attempts
std::unique_ptr
I can use std::unique_ptr for the file like so:
std::unique_ptr<std::ostream> p;
p = std::make_unique<std::ofstream>("file.txt");
*p << "hi there" << std::endl;
Trying this with std::cout warns me about a deleted function (assuming that's the constructor.
std::unique_ptr<std::ostream> p2;
p2 = std::make_unique<std::ostream>(std::cout);
*p2 << "hey" << std::endl;
std::shared_ptr
Because std::unique_ptr is only for owning things, and std::cout shouldn't be owned, I thought I'd try std::shared_ptr
std::shared_ptr<std::ostream> p;
p = std::make_shared<std::ostream>(std::cout);
*p << "hola" << std::endl;
It gives me the same deleted constructor error. p = &std::cout complains about a type mismatch, so it's also not working.
You can use a shared_ptr with a deleter that does not delete anything in the case of cerr and just a normally constructed shared_ptr in the case of ofstream
class Logger {
private:
std::shared_ptr<std::ostream> output_stream{ nullptr };
public:
Logger() :
output_stream(&std::cerr, [](std::ostream*){})
{ }
Logger(std::string file) :
output_stream(std::make_shared<std::ofstream>(file))
{ }
// default destructor is OK
template<typename T>
void log(T info)
{
*output_stream << info << std::endl;
}
};
I would just have two pointers, one smart and one raw.
The raw pointer is always used to refer to the stream. The smart pointer is just used for clean-up if needed.
class Logger {
private:
std::unique_ptr<std::ofstream> file_stream;
std:ostream *stream;
public:
Logger() : stream(&std::cerr) {}
Logger(const std::string& file)
: file_stream(std::make_unique<std::ofstream>(file)), stream(file_stream.get()){}
template<typename T>
void log(T info) {
*stream << info << std::endl;
}
};
I tend to try to avoid cases where I want an object to "own" such things. In the times I did not have much choice, I ended up settling with a "shouldDelete" flag or a callback.
class Logger {
public:
Logger(std::ofstream *outputStream, bool deleteOutputStream)
: outputStream(outputStream), deleteOutputStream(deleteOutputStream)
{ }
~Logger()
{
if (deleteOutputStream) delete outputStream;
}
};
Logger logger(&std::cout, false);
class Logger {
public:
typedef std::function<void(std::ostream*)> Deleter;
typedef std::unique_ptr<std::ostream, Deleter> OStreamPointer;
Logger(OStreamPointer &&outputStream)
: outputStream(std::move(outputStream))
{ }
~Logger() { }
private:
OStreamPointer outputStream;
};
Logger logger(Logger::OStreamPointer(
&std::cout,
[](std::ostream*) {})); //no-op callback
You could do this by releasing the smart pointer in the destructor (and elsewhere) in the cases where it shouldn't be deleted, but that's not worth the hassle IMO.
Instead, I'd recommend simply using two pointers: one for streams that need to be managed and one for those that don't:
class Logger {
private:
std::ostream * unmanaged_stream{ nullptr };
std::unique_ptr<std::ostream> managed_stream{ nullptr };
bool using_file{ false };
std::ostream& output_stream()
{
return using_file ? *managed_stream : *unmanaged_stream;
}
public:
Logger()
: unmanaged_stream{&std::cerr},
using_file{false}
{
}
Logger(const std::string& file)
: managed_stream{std::make_unique<std::ofstream>(file)},
using_file{true}
{
}
template<typename T>
void log(T info)
{
output_stream() << info << std::endl;
}
};
If saving space is a priority you could put them in a union, but then you'd have to explicitly call the destructor and placement new to define the active member, which again is more hassle and probably not worth it.
I am trying to make a Console class. I would like to wrap cin and cout in the class and overload the << and >> operators. So I could use the class as such:
// Output
Console << "Call cout from Console" << endl;
// Input
string str;
Console >> str; // Call cin
My best guess was:
class Console {
//...
public:
ostream& operator<< (ostream& os)
{
cout << os;
return &cout;
}
//...
};
But I know that's wrong, how could I overload the operators to use the Console class as both cin and cout?
I got a working code that can handle the stream manipulators. You can see my code in action in this Ideone page
Here is the code:
#include <iostream>
typedef std::ostream& (*manip) (std::ostream&);
class console {
};
template <class T> console& operator<< (console& con, const T& x) { std::cout << x; return con; }
template <class T> console& operator>>(console& con, T& x) { std::cin >>x; return con; }
console& operator<< (console& con, manip manipulator){ std::cout<<manipulator; return con;}
int main() {
console c;
int a,b;
c>>a>>b;
c << "hello world"<<std::endl<<std::hex<<(a+b)<<std::endl;
}
Thanks #MooingDuck for the discussion that led me to a working answer and #111111 for the start point.
I don't know why would want to do such a thing but it isn't the stream you need to capture but the other type. But if this is just to make std::cout and std::cin more convenient I wouldn't bother.
class console {
};
template<typename T>
console& operator<<(console con, const T& val) {
std::cout << val;
return con;
}
console c;
c << "hello world\n";
This is not direct answer to your question, but maybe I point you out some alternative.
See my answer to some other question. To define yourself all of these <<and >> operators is not very easy. However you can overwrite streambuf for Console. Use combined streambufs of cin and cout,
Derive your console from std::iostream and your streambuf from std::streambuf
class console_streambuf : public std::streambuf {
public:
console_streambuf() {
// no buffering, overflow on every char
setp(0, 0);
}
virtual int_type overflow(int_type c) {
std::cout << c;
return c;
}
...
};
class console : public std::iostream {
public:
console() { rdbuf(&buf); }
private:
console_streambuf buf;
};
Contrary to many of the answers above, doing what you want is pretty simple, using the magic of templates.
I'd recommend using a stringstream, because using an ostream (cout is an ostream) can require arcane black magic (no joke).
#include <string>
#include <iostream>
#include <sstream>
struct console {
std::stringstream data_;
console() : data_() { };
// We make ourselves a template sink so we can "take" operator<<'s.
// The awesome advantage to using a template like this is that the
// compiler will allow us to "take" any data that can be converted
// to a stringstream, which will handle converting int's etc.
// for us!
template<typename T>
console& operator<<(const T& what) {
data_ << what;
return *this; // We must return a reference if we want to
// string together more than one thing, i.e.
// b << " " << 4;
}
void flush() {
std::cout << data_.str();
data_.clear();
std::cout.flush();
}
};
int main()
{
int a = 4;
console b;
console c;
b.data_ << 2;
c.data_ << 4;
//b << std::cout; // WHAT? it's possible but stupid, prints garbage
// Because we made the template return a reference, this will
// allow us to chain things just like we do with cout.
b << " HELLO WORLD! " << "yo!" << 4;
b << a << " " << 4.2f;
// Compiler chokes on this. It will try to convert "console"
// to a stringstream which it can't.
//b << c;
b.flush(); // Send out the output
// Wait for key press
char foo[500];
gets(foo);
}
Output:
2 HELLO WORLD! yo!44 4.2
Just like cout, except of course with more control.
You can get into using basic_ostream's and basic_istreams if you want binary I/O, but I'd recommend against it unless you really really need it.
Overloaded operator functions must be declared with the specific types you're going to call them with on the left and right. So you will need an operator<< (int), operator<< (double), operator<< (const std::string &), etc.
If you're really just going to pass them on to cin and cout, you can save typing by using a template member function, like:
template <class T> Console& operator<< (const T& x) { cout << x; return *this; }
[thanks to André for pointing out it should return Console& so you can string together calls like Console << a << b; ]
I am trying to write a thread safe logger class so that i can do the exact same as with cout but with thread safety.
here is the logger class (still working on the type of lock required)
class logger {
public:
logger(LOGGER::output_type type);
logger(const logger& orig);
virtual ~logger();
template <typename T>
logger & operator << (const T & data){
boost::mutex::scoped_lock io_mutex_lock(io_mutex);
(*out)<<data;
return *this;
}
private:
static boost::mutex io_mutex;
std::ostream * out;
};
The poblem is I cannot do the following
log<<"asdfg";
I have to instead do
log<<string("asdfg");
int i = 10;
log<<string ("i = ") << i << endl;
following is the compilation error.
gcc.compile.c++ src/simpleThread/bin/gcc-4.4.5/debug/simpleThread.o
src/simpleThread/simpleThread.cc: In function ‘int main()’:
src/simpleThread/simpleThread.cc:28: error: no match for ‘operator<<’ in ‘((logger*)logOut.logger::operator<< [with T = char [18]](((const char (&)[18])"fibonacci thread ")))->logger::operator<< [with T = int](((const int&)((const int*)(& i)))) << std::endl’
So I guess i am missing some important concept of C++. Please let me know what it is?
Is my requirement even achievable
thanks,
Kiran
Note that your logger class is still not thread safe:
int i = 10;
log <<string ("i = ") << i << endl;
There is nothing stopping this thread from getting preempted by another another thread printing to logger and producing something like:
i = i = 12
Instead of:
i = 1
i = 2
If you have a compiler with variadic templates, here's one way of fixing this:
#include <ostream>
#include <mutex>
inline void sub_print(std::ostream&) {}
template <class A0, class ...Args>
void
sub_print(std::ostream& os, const A0& a0, const Args& ...args)
{
os << a0;
sub_print(os, args...);
}
std::mutex&
io_mut()
{
static std::mutex m;
return m;
}
template <class ...Args>
void
log(std::ostream& os, const Args& ...args)
{
std::lock_guard<std::mutex> _(io_mut());
sub_print(os, args...);
os.flush();
}
#include <iostream>
int main()
{
int i = 10;
log(std::cout, "i = ", i, '\n');
}
I.e. the mutex is locked until all arguments for given log message are processed. std::endl is handled separately by always flushing the stream after every message.
Your problem is that logger isn't a stream, so the usual stream operators will not work, just the single one you have defined.
You can get endl to work by defining it yourself:
inline logger& endl(logger& log)
{
// do something to *out
return log;
}
Now log << "Hello!" << endl; will work.
To be able to chain several << operations together like the streams do, you will have to define all the operators for the logger (just like the streams do).
I think you are introducing synchronization at too low a level. To understand why, assume thread 1 executes:
log << "This is " << "my " << "log message" << endl;
while thread 2 executes:
log << "Hello, " << "World!" << endl;
In such a case, the log file (or console output) may contain interleaved messages, for example:
This is Hello, my World!
log message
To avoid this problem, your application will have to construct
an entire message as a single string, and only then pass that string to a logger object. For example:
ostringstream msg;
msg << "This is " << "my " << "log message" << endl;
log << msg.str();
If you take this approach, then your logger class does not need to overload operator<< for endl and multiple types.
I tested your program with some simplifications as follows, and it compiles and runs fine, which means that the problem is probably elsewhere:
#include <iostream>
class logger {
public:
// logger(LOGGER::output_type type);
logger(std::ostream& os): out(&os) {}
~logger() {}
template <typename T>
logger & operator << (const T & data){
// boost::mutex::scoped_lock io_mutex_lock(io_mutex);
(*out)<<data;
return *this;
}
private:
// static boost::mutex io_mutex;
std::ostream * out;
};
int main()
{
logger log(std::cout);
log << std::string("hello ");
log << "world\n";
}
After digging into iostreams and with hints from Bo Persson, I think i found a better solutions since I dont need to write a function each for each ios manipulator. So here it is
logger& operator<<(std::ostream& (*pf)(std::ostream&)) {
(*out)<<pf;
return *this;
}
For an explanation search for iostreams and applicators.
Here is the complete boost::thread safe implementation (requires some refactoring and optimization probably) using some hints from Ciaran-Mchale
/*
* File: logger.h
* Author: Kiran Mohan
*
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <boost/thread.hpp>
#include <iostream>
namespace LOG {
enum output_type {
STDOUT,
STDERR
};
/**
* a thread safe logger to print to stdout or stderr
*/
class logger {
public:
logger(LOG::output_type type);
logger(const logger& orig);
virtual ~logger();
template <typename T>
logger & operator <<(T data) {
/* Takes any data type and stores in a stringstream
*/
(*oss) << data;
return *this;
}
logger & operator<<(std::ostream& (*pf)(std::ostream&)) {
// for stream manipulators
(*oss) << pf;
return *this;
}
logger & operator<<(logger & (*pf)(logger &)) {
//applicator - mainly calling the print function;
return pf(*this);
}
friend logger & flush(logger & l);
logger & print() {
boost::mutex::scoped_lock io_mutex_lock(io_mutex);
(*out) << oss->str() << std::flush;
delete oss;
oss = new std::ostringstream;
return *this;
}
private:
static boost::mutex io_mutex;
std::ostream * out;
std::ostringstream * oss;
};
logger & flush(logger & l);
};
#endif /* LOGGER_H */
/*
* File: logger.cc
* Author: aryan
*
*/
#include <boost/thread/pthread/mutex.hpp>
#include <iostream>
#include "logger.h"
using namespace LOG;
boost::mutex logger::io_mutex;
logger::logger(LOG::output_type type) {
if (type == LOG::STDOUT) {
out = &std::cout;
} else {
out = &std::cerr;
}
oss = new std::ostringstream;
}
logger::logger(const logger& orig) {
out = orig.out;
}
logger::~logger() {
delete oss;
}
logger & LOG::flush(logger & l) {
l.print();
boost::this_thread::yield();
return l;
}
use it like this
LOG::logger logOut (LOG::STDOUT);
logOut<<"Hello World\n"<<LOG::flush;
I have a C++ class MyObject and I want to be able to feed this data like I would to a osstream (but unlike a direct sstream, have the incoming data be formatted a special way). I can't seem to figure out how to overload a operator for MyObject to eat input given to it.
class MyObject {
public:
ostringstream s;
FEEDME
};
int main() {
MyObject obj;
obj.FEEDME << "Hello" << 12345;
// I want obj.s == ":Hello::12345:"
}
I want it so every item fed in be surrounded by : :
So in the given example, s = ":Hello::12345" should be the final outcome. What my question is, how can I tell the object that when ever a <<something, put : : around the something.
Is this possible?
try this:
class MyObject {
public:
template <class T>
MyObject &operator<<(const T &x) {
s << ':' << x << ':';
return *this;
}
std::string to_string() const { return s.str(); }
private:
std::ostringstream s;
};
MyObject obj;
obj << "Hello" << 12345;
std::cout << obj.to_string() << std::endl;
There are certain things you won't be able to shove into the stream, but it should work for all the basics.
You may find the answers for How do I create my own ostream/streambuf? helpful.
I would take a slightly different approach and create a formater object.
The formater object would then handle the inserting of format character when it is applied to a stream.
#include <iostream>
template<typename T>
class Format
{
public:
Format(T const& d):m_data(d) {}
private:
template<typename Y>
friend std::ostream& operator<<(std::ostream& str,Format<Y> const& data);
T const& m_data;
};
template<typename T>
Format<T> make_Format(T const& data) {return Format<T>(data);}
template<typename T>
std::ostream& operator<<(std::ostream& str,Format<T> const& data)
{
str << ":" << data.m_data << ":";
}
int main()
{
std::cout << make_Format("Hello") << make_Format(123);
}