Написание отладочной сборки только утверждение функции, игнорирующее побочные эффекты

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

bool const isDebugMode()
{
return false;  // Will be controlled by preprocessor flag.
}
void assertWithReason(bool const condition, std::string const reason = "")
{
if (isDebugMode() and not condition)
{
abort();
}
}

Я думаю, что некоторый побочный эффект в выражении условия препятствует устранению вызова утверждения.

Например,

assertWithReason(glGetError() == GL_NO_ERROR);

Я ожидал, что этот вызов утверждения будет устранен, но это не так. Потому что он выполняется перед проверкой debug-build.

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

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

Я использую Clang, и расширение, специфичное для компилятора (например, атрибут GCC), тоже подойдет.

0

Решение

Мне очень нравится использовать макросы для этой цели. Да, я знаю, Макросы злой, но точно так же, как ножи (использованные неправильно) являются злом, они пригодятся, если вы используете их правильно.

 #define MY_ASSERT(x) do {\
if (is_debug() && !x) assertFailed(__FILE__, __LINE__, __FUNCTION__, #x);\
} while(0);

Теперь вы также можете показать, где это не удалось (my_drawfunc.cpp: 34 : my_do_draw(): assertion failed: glGetError == GL_NO_ERROR или что-то типа того.

2

Другие решения

В C ++ 11 вы можете использовать лямбда-выражения. Вполне вероятно, что постоянное распространение сделает так, что is_debug никогда не будет оценен, и даже если это так, лямбда не вызывается.

class Debug { enum { is_debug = 1; } };

template <class F>
void assert(F f) {
if (is_debug && !f()) abort();
}

{
int x = 6;
assert([&]() { return x == 6; });
}
1