为 class 包装字符串流重载 ostream 运算符

Overloading the ostream operator for a class wrapping stringstream

我目前正在编写 class 来包装 stringstream。我的总体目标是为我的字符串流提供线程安全的 << (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 ; 
}

如上所述,它无法编译,我理解这一点,因为我将 WrappedStringStream 作为 const 参数传递并调用不是 const 的 AddValue - 导致丢弃限定符错误。

这是解决方案

#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

========编辑==========
本来我并没有安静地理解提问者的最终目标是什么,而是专注于如何修复他的语法 issue.It 在多线程环境中使用 << 不是一个好主意。我们有一个 Log class,在我们的 log class 中,我们只有一个 Log 方法,它采用可变数量的参数。这将解决问题。
尽管如此,还是有一个使用 << 锁定线程的解决方案,但真的很急,不推荐。缺点很明显——如果您忘记添加 'LoggingStart' 和 'LoggingEnd',您可能会遇到死锁。
也感谢@RemyLebeau,它应该 return *this 而不是 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;
}