Макрос для регистрации ошибки и возврата false - PullRequest
0 голосов
/ 27 июля 2011

Большинство операторов в проекте, с которым я работаю, имеют форму

if(!someObject->someFunction(arg1,arg2))
{
    cerr << "Something bad happened. Args are: " << arg1.print() << " " << arg2  << endl;
    return false;
}

Это делает мой код не читаемым, так как регистрация ошибок утраивает фактический код.Поэтому я написал следующий макрос:

#define ReturnFalse(error) \
  ({ \
   cerr << error << "@File: " << __FILE__ << "Line: " << __LINE__ << endl; \
   return false; \
   false; \
   }) \

Теперь я могу использовать его как

someObject->someFunction(arg1,arg2) || ReturnFalse("Something bad happened.Args are:" << arg1.print() << " " << arg2 );

. Это работает, но я боюсь, что буду следовать плохой практике.

  1. Является ли код недопустимым / неопределенным?
  2. С точки зрения производительности, это немного хуже, чем если бы?
  3. Мой vim не распознает форматирование и выделение, как будтоесть некоторая синтаксическая ошибка.Есть ли способ исправить это?
  4. Есть ли лучший способ записать сообщение и вернуться с аккуратным синтаксисом?
  5. Непросто, чтобы макрос мог вернуться из функции.Поэтому я назвал это ReturnFalse.Кто-нибудь может предложить лучшее имя?

Редактировать:

Спасибо за все ответы. Есть ли стандартный способ сделать это с помощью операторов запятых?Я не могу понять это правильно.

Ответы [ 3 ]

2 голосов
/ 27 июля 2011

Код не соответствует стандарту C ++ и не является переносимым.

({..})

- это расширение компилятора gcc, которое называется Выражение оператора .

Если вы скомпилируете свой код с флагом -pedantic, и он скажет вам, что он не соответствует стандарту.

Если вы не беспокоитесь о переносимости исходного кода между различными компиляторами, вам следует воздерживаться от использования любых конструкций кода, которые не поддерживаются стандартом C ++ и являются просто расширениями компилятора.

0 голосов
/ 27 июля 2011

Если вам нужен лучший метод обработки ошибок в программе на C ++, вам, вероятно, стоит взглянуть на Приложение E Специального издания TCPL. Лучше избегать макро магии, если вы можете. В приложении обсуждаются методы, которые будут использоваться при обработке ошибок. Это также доступно в: http://www2.research.att.com/~bs/3rd_safe.pdf

РЕДАКТИРОВАТЬ: И для случая магии макроса, используя запятую ... Это может быть возможным путем:

 #define ReturnFalse(error,a1,a2) \
 ({ \
  cerr << error << "@File: " << __FILE__ << "Line: " << __LINE__ << #a1<<" "<<#a2 <<endl; \
  return false; \
  false; \
 })

вариант использования: ReturnFalse("Something bad happened.", arg1 , arg2)

0 голосов
/ 27 июля 2011

Я думаю, что лучше бы это была функция:

bool fnAssert(bool cond, char * strCond, char *msg, char *file, int line)
{
    if (!cond)
    {
        cerr << "@File: " << file << ":" << line << " " << strCond << " failed."
              << msg << endl;
    }
    return cond;
}

#define Assert(cond, a) fnAssert(cond, #cond, a, __FILE__, __LINE__)

Таким образом, он переносим на все компиляторы, будет показывать подсветку синтаксиса, а макрос позволяет автоматически вставлять имя файла и номер строки. Вы также сможете распечатать сбойное условие и установить точки останова при его отладке.

редактировать

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

#define ReturnOnAssert(cond, a, b) if (! Assert(cond,a) ) return b;

Теперь, когда вы пишете заявление:

ReturnOnAssert(isItBad, "Something bad happened", retVal);

или

DoWhatever(), ReturnOnAssert(isItBad, "Something bad happenedAgain", retVal);

Вы вернетесь из своей функции со значением retVal, если isItBad равно false.

НО - сокрытие return в макросе - это большое НЕТ-НЕТ ИМХО. Не делай этого. Что вы пытаетесь сохранить, 2 строки кода на if?

...