Изменение стратегии обработки ошибок
От: enji  
Дата: 01.09.11 08:20
Оценка:
Есть библиотека (с исходниками), в которой сообщения об ошибках выдаются вот так:
#define LOG(level)   std::cerr << #level ": "

bool someFunction()
{
  if (error)
  {
    LOG(ERROR) << "message";
    return false;
  }
  return true;   
}


Хочется с минимальными усилиями написать обертку, которая будет кидать исключение с описанием произошедшего:

void someFunctionWrapper()
{
  if (!someFunction())
   throw std::runtime_error("тут надо как-то узнать сообщение об ошибке")  
}


Я думаю сделать как-то так:
class ErrStream
{
  boost::thread_ptr<std::ostringstream> err;

public:
  void beforeCall() { if (!err) err.reset(new  std::ostringstream); }
  void afterCall() 
  { 
    std::string s = err->str(); 
    if (!s.empty())
    { 
      err.reset();  
      throw std::runtime_error(s); 
    } 
  }
  
  template<class T>
  ErrStream& operator<<(const T&v) { *err << v; return *this; } 

  static ErrStream& get() { static ErrStream err; return err; }
};

struct ErrGuard
{
  ErrGuard() { ErrStream::get().beforeCall(); }
  ~ErrGuard() { ErrStream::get().afterCall(); } // да, деструктор кидает исключения. Однако сама библиотека исключения не кидает
};

#define LOG(level)   ErrStream::get() << #level ": "

void someFunctionWrapper()
{
  ErrGuard g;
  someFunction();
}


Какие тут могут быть грабли? Может можно сделать проще?

Вариант — кидать исключение внутри макроса LOG не годится — библиотека во многих местах явно зовет delete.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.