错误报告仅

时间:2015-11-13 14:22:12

标签: c++ error-handling

我正在编写一些处理大量数据的代码。当发生错误时,通常会发生错误多次发生,因此我只想报告一次。我遇到的问题是,我希望有个别错误消息。在C我会使用一个带有可变参数的方法,当然这不是真正的类型安全,所以我想知道如何在C ++中使用typesafe输出实现相同的功能。我知道我可以stringstream并创建单独的字符串,但这意味着我必须创建完整的错误消息,即使它已被丢弃,因为它已经打印过,而且stringstream也不是很快。

所以目前我使用这样的代码:

    std::string key = "BT:EMPTY";
    if(mErrorReport.find(key) == mErrorReport.end())
    {
        std::cerr << "ERROR [" << Name<< "] Type is empty! " << std::endl;
        mErrorReport.insert(key);
    }

    std::string key = "UI:"+Unitcode;
    if(mErrorReport.find(key) == mErrorReport.end())
    {
        std::cerr << "ERROR [" << Name<< "] Room with the id " << Unitcode << " doesn't exist! " << std::endl;
        mErrorReport.insert(key);
    }

    ...

在C中,我会编写一个像这样的可变函数:

 void ErrorLog(const char *key, int nLogLevel, const char fmt, ...)
 {
      // Check if this error was already reported before.
      if(mErrorLog.find(key) == mErrorLog.end())
      {
          fprintf(stderr, fmt, ...);
          mErrorLog.insert(key);
      }
 }

所以我想知道是否有一些类似的最佳实践。

1 个答案:

答案 0 :(得分:0)

为什么不使用

void ErrorLog(const std::string& key, const std::string& name, const std::string& what)
{
    if (mErrorLog.find(key) == mErrorLog.end())
    {
        std::cerr << "ERROR[" << name << "]" << what << std::endl;
        mErrorLog.insert(key);
    }
}

并将其称为

ErrorLog("BT:EMPTY", Name, "Type is empty!");
ErrorLog("UI:" + Unitcode, Name, std::string("Room with the id ") + Unitcode + " doesn't exist!");

如果Name未发生变化,您可以删除该参数,然后将其添加到std::err来电。

更新替代解决方案

class ErrorLogWriter
{
public:

    ErrorLogWriter(const std::string& name, const std::string& key, std::set<std::string>& log)
        :m_name(name)
        , m_key(key)
        , m_log(log)
    {}

    ErrorLogWriter& operator<<(const std::string& msg)
    {
        if (m_log.find(m_key) == m_log.end())
        {
            std::cerr << "ERROR[" << m_name << "]" << msg << std::endl;
            m_log.insert(m_key);
        }
        return *this;
    }

private:
    std::string m_name;
    std::string m_key;
    std::set<std::string>& m_log;
};

class ErrorLog
{
public:

    ErrorLog(const std::string& name, std::set<std::string>& log)
        :m_name(name)
        ,m_log(log)
    {}

    ErrorLogWriter operator()(const std::string& key)
    {
        return ErrorLogWriter(m_name, key, m_log);
    }

private:
    std::string m_name;
    std::set<std::string>& m_log;
};

int main()
{
    std::string Name = "NAME";
    std::string Unitcode = "UNITCODE";
    std::set<std::string> mErrorLog;

    ErrorLog log(Name, mErrorLog);

    log("BT:EMPTY") << "Type is empty!";
    log("UI:" + Unitcode) << "Room with the id " << Unitcode << " doesn't exist!";
}