Как написать условие if, которое компилируется только когда DEBUG равен #defined? - PullRequest
4 голосов
/ 23 июня 2010

Мне нужна помощь в написании макроса для условия if, который компилируется, только когда флаг DEBUG определен директивой #define.

Вот пример, который иллюстрирует то, что я хочу. Первый фрагмент кода показывает обычный способ записи условия if с помощью # ifdef.

#ifdef DEBUG
if( rv == false )
{
     string errorStr = "error in return value" ;
     cout << errorStr << endl ;
     throw( Exception(errorStr) ) ;
}

Я хочу написать это так, как показано ниже:

DEBUG_IF( rv==false )
{
     same code as above
}

Кажется, все просто, но у меня проблемы с определением макроса, который может это сделать. Если кто-то испытал это раньше, пожалуйста, помогите.

Спасибо.

Ответы [ 7 ]

9 голосов
/ 23 июня 2010

Попробуйте:

#ifdef DEBUG
  #define DEBUG_IF(x) if(x)
#else
  #define DEBUG_IF(x) if(false)
#endif

Теперь это не будет точно так же, как у вас сейчас, потому что при использовании этого метода код внутри блока if все еще компилируется, хотя он никогда не будет run , когда DEBUG не определено и, вероятно, будет оптимизировано. Напротив, в вашем исходном примере код исключается препроцессором и даже не компилируется.

2 голосов
/ 23 июня 2010

Я думаю, это то, что вы ищете:

#include <iostream>

#ifdef DEBUG
#define DEBUG_IF(cond) if(cond)
#else
#define DEBUG_IF(cond) if(false)
#endif

int main(int argc, char** argv)
{
  DEBUG_IF(argc > 1)
  {
     std::cout << "In debug mode and at least one argument given" << std::endl;
  }
  else
  {
    std::cout << "Not in debug mode or no arguments given" << std::endl;
  }
}

Запустите это из командной строки, с аргументом или без аргумента, с или без компиляции с -DDEBUG, чтобы доказать, что это работаеткак и ожидалось.

1 голос
/ 23 июня 2010

ИМХО, лучший подход

#ifdef DEBUG
if(blah){
    dostuff();
}
#endif
0 голосов
/ 30 июня 2017

Несколько поздно здесь, но мне было интересно, может ли простое определение константы более элегантно, чем определение функции:

#ifdef DEBUG
    #define IS_IN_DEBUG true
#else
    #define IS_IN_DEBUG false
#endif

if ( IS_IN_DEBUG ) {
  // do something
}

Разве это не легче читать? Есть мысли по этому поводу?

0 голосов
/ 24 июня 2010

Я не рекомендую использовать макрос типа DEBUG_IF по причине, указанной Келли.

DEBUG_IF(x)
{
    // debugging code
}
else
{
    // release code (should be executed for both debug and release)
}

Видите логическую ошибку здесь? Код релиза всегда должен выполняться, если только он не является кодом релиза, но сделать это было бы довольно легко с помощью макроса DEBUG_IF. Это может быть неприятно, чтобы написать это, но я думаю, что это самый ясный и наименее запутанный способ. Если вы используете его, я рекомендую избегать его полностью.

То же самое верно для макроса DEBUG_CONDITION.

if (DEBUG_CONDITION(x) )
{
    // debugging code
}
else
{
    // oops, this never gets executed in debug builds
}

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

Идея отладки крупномасштабной системы, заполненной такими макросами DEBUG_IF / DEBUG_CONDITION, как эта, вызывает у меня головную боль расщепления.

0 голосов
/ 23 июня 2010

Лично я бы пошел с маршрутом #ifdef DEBUG вместо кода запутывания DEBUG_IF макроподхода. Лучше написать чистый код, который не скрывает код за каким-либо макросом.

Если вы действительно хотите пройти макро-маршрут, я бы оставил if в покое и сосредоточился бы на самом условии, например,

#ifdef DEBUG
# define DEBUG_CONDITION(x) x
#else
# define DEBUG_CONDITION(x) false
#endif  /* DEBUG */

if (DEBUG_CONDITION(rv == false))
{
   ...
}

В этом подходе все еще существует некоторая путаница, но, на мой взгляд, он более приемлем, чем предлагаемый макрос DEBUG_IF(), поскольку он сохраняет синтаксис C / C ++.

Я полагаю, что большинство, если не все, компиляторы просто оптимизируют мертвый код, полученный в результате if(false) в не DEBUG случае (например, эквивалентном if(0)). Однако некоторые компиляторы могли бы выдавать предупреждение «мертвый код» с этим подходом, а также с подходом DEBUG_IF(), который вы описали.

0 голосов
/ 23 июня 2010

Вы хотите, чтобы if был условным, чтобы в Release выпускался безоговорочно?(Как следует из заголовка.) Или вы хотите, чтобы весь блок был условным?(Таким образом, в Release нет блока.) В вашем коде эквивалентности отсутствует #endif, поэтому невозможно сказать.

Для первого вы можете использовать это:

#ifdef DEBUG
    #define DEBUG_IF(x) if (x)
#else
    #define DEBUG_IF(x) if (false)
#endif

Код в блоке будет скомпилирован, но компилятором отброшен, так как это мертвый код.Если вы хотите, чтобы условное условие было изменено, сделайте следующее:

#ifdef DEBUG
    #define DEBUG_IF(x) if (x)
#else
    #define DEBUG_IF(x)
#endif

Без DEBUG, все условное выражение перестает существовать.Исправьте свой вопрос, чтобы было понятно, чего вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...