超负荷的按钮包裹串流的操作员

Overloading the ostream operator for a class wrapping stringstream

本文关键字:操作员 包裹 按钮 超负荷      更新时间:2023-10-16

我目前正在写一堂课来包装弦乐。我的总体目标是提供线程安全<<(Ostream(我的弦乐。我很难弄清楚我要做的事情的正确语法。任何帮助都是最感激的!

下面您会找到我尝试的东西。我知道这不是正确的语法,而是我要拍摄的。我当然不能超载<<操作员和迫使用户使用addValue,但这不是编写代码时快速简便的字符串操作的理想选择。

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 ; 
}

如上所述,它没有编译,我理解这是因为我将包装式流程作为const参数和调用addValue,而不是const,这导致了丢弃的预选程序错误。

这是解决方案

#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;
}

输出

This is a string, 56.78

=====================
最初,我并不安静地理解发问者的最终目标,而只是关注如何解决他的语法问题。使用&lt;&lt;这不是一个好主意。在多线程环境中。我们有一个日志类,在我们的日志类中,我们只有一个日志方法,该方法采用可变数量的参数。这将解决问题。
尽管如此,仍然有一个用于使用&lt;&lt;锁定线程,但真的很艰难,不建议。缺点是显而易见的 - 如果您忘了添加" Loggingstart"answers" Loggingend",您可能会陷入僵局。
还要感谢@RemyLebeau,它应该返回 *而不是m_stringstream。

请参阅下面的代码。

#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;
}