Перегрузка оператора ostream для переноса строк класса - PullRequest
1 голос
/ 09 мая 2019

В настоящее время я пишу класс для переноса потока строк. Моя общая цель - обеспечить потокобезопасный << (ostream) для моего stringstream. У меня проблемы с определением правильного синтаксиса того, что я пытаюсь сделать. Любая помощь будет самой благодарной! </p>

Ниже вы найдете то, что я пробовал. Я знаю, что это неправильный синтаксис, но это то, для чего я стреляю. Конечно, я не мог бы перегружать оператор << и заставлять пользователей использовать AddValue, но это не было бы идеально для быстрой и простой манипуляции со строками во время написания кода. </p>

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 и вызываю AddValue, который не является const - что приводит к ошибке квалификатора сбросов.

1 Ответ

0 голосов
/ 09 мая 2019

Вот решение

#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

======== edit ==========
Изначально я не спешил понять, какова конечная цель спрашивающего, а просто сосредоточился на том, как исправить его синтаксическую проблему. Не рекомендуется использовать << в многопоточной среде. У нас есть класс Log, а в нашем классе log есть только метод Log, который принимает переменное количество параметров. Это решит проблему. <br/> Тем не менее, есть решение использовать << для блокировки потока, но очень срочно и НЕ рекомендую. Недостаток очевиден - если вы забыли добавить «LoggingStart» и «LoggingEnd», вы можете оказаться в тупике. <br/> Также спасибо @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;
}
...