【问题标题】:How to get the end of a C++ string stream?如何获得 C++ 字符串流的结尾?
【发布时间】:2010-11-20 17:53:39
【问题描述】:

我正在向我的(简单)log class 添加函数,使其像流一样可用。 目前,经过一些修改,我得到了这个(在我的 cpp 中):

// blah blah blah...
// note: here String is a defined as: typedef std::string String;

void Log::logMessage( const String& message )
    {
        logText(); // to be sure we flush the current text if any (when "composing" a message)
        addText( message ); 
        logText(); // really log the message and make the current text empty
    }

// blah blah blah...

    Log& operator<<( Log& log, const std::stringstream& message )
    {
        log.logMessage( message.str() );
        return log;
    }

    Log& operator<<( Log& log, const String& message )
    {
        log.addText( message );
        return log;
    }

现在在我的“客户端”应用程序中,我使用此代码检查结果(您已经猜到,m_log 是一个有效指针):

gcore::Log& log = *m_log;
log << getName() << " : application created.";
log << "This is a test for " << getName();

现在我遇到的问题是 logText()(和 logMessage)永远不会被调用,因为这个测试代码只会用字符串调用

log << getName() << " : application created."; 

相当于

log.addText( getName() );
log.addText( " : application create." );
log.logText();

我不确定如何执行此操作,或者即使可能。我的第一个猜测是可以像这样在流的末尾使用 std::endl :

log << getName() << " : application created." << std::endl; 

或等效的东西,但如果可以在不向流中添加对象的情况下做到这一点,那就太好了。

有什么想法吗?

【问题讨论】:

  • 为什么延迟到 logText() 被调用,才能真正记录消息?
  • 是的,addText() 将填充 std::stringstream 而 logText() 将做一些工作来“记录”流的字符串结果。 logText() 将字符串值写入文件和标准流中并添加一些时间信息,因此只有在调用 logText() 时才必须考虑完成“日志”。如果文本为空,则忽略调用。

标签: c++ string stream


【解决方案1】:

您可以创建一个临时对象并使用他的析构函数来捕获语句的结尾:

下面的代码应该会给你基本的想法

class Log
{
public:
  class Sublog
  {
  public:
    Sublog(const std::string& message)
    {
      std::cout << message;
    }

    void addText(const std::string& message)
    {
      std::cout << message;
    }

    ~Sublog()
    {
      std::cout << std::endl;
    }

    Sublog& operator<<(const std::string& message )
    {
      this->addText(message);
      return *this;
    }
  };

};

Log::Sublog operator<<( Log& log, const std::string& message )
{
  return Log::Sublog(message);
}

会这样使用

int main()
{
    Log log;
    log << "Foo" << "bar";
    log << "baz" << "plop";
}

在每个分号之后,调用Sublog的析构函数


Klaim:就我而言,这个解决方案的(有效的)实施:

在日志标题中:

    /** To allow streaming semantic on logs (used in << operator) .
*/
class LogStreamer
{
public:

    LogStreamer( Log& log, const String& text )
        : m_log( log )
    {
        m_log.addText( text );
    }

    ~LogStreamer()
    {
        m_log.logText();
    }

    LogStreamer& operator<<( const String& text )
    {
        m_log.addText( text );
        return *this;
    }

private:

    Log& m_log;

};

GCORE_API LogStreamer operator<<( Log& log, const String& message );

在cpp文件中:

LogStreamer operator<<( Log& log, const String& message )
{
    return LogStreamer( log, message );
}

【讨论】:

  • 哇,使用临时对象及其析构函数,没想到这一点。 +1
  • 谢谢,它醒来真的很好,只有一个很小的临时对象!我将编辑帖子以提供当前的完整解决方案,因为必须修复一些细节。
猜你喜欢
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多