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

时间:2019-05-09 20:40:58

标签: c++ stringstream ostream istream

我目前正在写一个包装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,导致了丢弃限定符错误。

1 个答案:

答案 0 :(得分:-1)

这是解决方案

#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

=========编辑=========
最初我并不是很安静地了解提问者的最终目标,而只是专注于如何解决他的语法问题。在多线程环境中使用<<不是一个好主意。我们有一个Log类,在我们的日志类中,我们只有一个Log方法,该方法需要可变数量的参数。这样可以解决问题。
仍然有一种使用<<来锁定线程的解决方案,但真的很急,不建议这样做。缺点很明显-如果您忘记添加'LoggingStart'和'LoggingEnd',则可能会陷入僵局。
也要感谢@RemyLebeau,它应该返回* 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;
}