问题
I'm currently writing a wrapper for STL stream to synchronize write calls from multiple threads. I have the following (simplified) code:
class Synchronize {
private:
std::stringstream ss;
public:
void write(std::string& str) {
// locking ...
ss << str;
// unlocking ...
};
// other stuff ..
};
Synchronize& operator<<(Synchronize& o, std::string& str) {
o.write(str);
return o;
}
Synchronize& operator<<(Synchronize* o, std::string& str) {
o->write(str);
return *o;
}
Its now possible to call the write()
method by using the <<
operator on an object of the Synchronize
class, but only by using a std::string
. And std::stringstream
also takes a lot of other stuff like int
s and float
s.
Is it possible to add this functionality to my Synchronize
class without a ton of own operator<<
functions? Would templates help? Or should I extend some class from the iostream
library?
回答1:
You can turn your operator overload into a friend template
Inside your class write
template<typename T>
friend Synchronize& operator<<(Synchronize& o, T const& t);
Then the definition could be
template<typename T>
Synchronize& operator<<(Synchronize& o, T const& t) {
o.write(t);
return o;
}
//edit
template<typename T>
void Synchronize::write(T& t)
{
ss << t;
}
回答2:
If I understand correctly, you want to have many readers into a single destination. The architecture you created (a wrapper on std::stream with synchronized/locked writing) is not a good solution.
Here's code that doesn't work as you would expect:
Synchronize your_stream;
void thread_function1()
{
output << "this is a message " << "from thread_function1\n";
}
void thread_function2()
{
output << "this is a message " << "from thread_function2\n";
}
With your code, the output may be:
this is a message this is a message from thread_function2
from thread_function1
What you need is the ability to set synchronization points wherever/whenever you want:
your_stream out;
out << synchronize_begin << "this is " << " a test" << synchronize_end;
(this buffers everything in a synchronize_begin
object (which can be dumped into a stream) and when it receives a synchronize_end
object, it locks a mutex
(shared with other synchronize_begin
instances) and writes to out
).
or:
std::ostream out; // any std::ostream type
out << synchronized << "this is " << " a test"; // synchronized ends here
(synchronized is a buffer instance that exits scope at the end of the line; when it is written into out, it locks, then writes it's data.
来源:https://stackoverflow.com/questions/14752504/wrapper-class-for-stl-stream-forward-operator-calls