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

标签 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 - 导致丢弃限定符错误。

最佳答案

解决方法

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

关于c++ - 为包装字符串流的类重载 ostream 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56067258/

相关文章:

c++ - 这个 static_assert 会被触发吗?

c++ - Execvp 仅正确运行第一个命令

c++ - 哪个更高效/整洁 : clearing an existing stringstream or creating a new one?

c++ - 如何处理模板类中的 ostream 运算符重载

c++ - 输出以空格分隔的列表

c++ - 如何阻止和唤醒 boost 线程?

c++ - Centos 7安装HHVM报错"Internal compiler"

c++ - 为什么 {fmt} 比 std::stringstream 慢?

c++ - 使用stringstream 将string 转换为int 的效率如何?

c++ - 'std::ios_base::ios_base(const std::ios_base&)' is private' 错误,同时为 std::ostram 重载运算符 <<