2015-05-14 3 views
2

Утверждения для использования в контексте, как:Как реализовать отладочное утверждение runtime без макросов в C++ 11/14 с безопасностью типа?

ASSERT(dynamic_cast<Derived*>(_ptr)); 
ptr = static_cast<Derived*>(ptr); 

Так во время отладки утверждения будет проверять динамическое приведение, но будет удалено в режиме выпуска. (стандартное утверждение)

Как реализовать это без макросов. Я подумал:

void ASSERT(bool _arg) 
{ 
    if(!_arg) 
     //something 
} 

Однако это не гарантирует безопасность типа. Кроме того, я думал о том, что у меня две реализации: пустая (для выпуска, поэтому функция ASSERT ничего не делает), а другая - с кодом выше для отладки. Этот метод также будет полагаться на компилятор, оптимизирующий пустую функцию, что не всегда является надежным.

Таким образом, что было бы лучшим способом? Или макросы абсолютно необходимы ...?

+2

Я бы предпочел макрос, потому что он позволяет добавлять дополнительные данные, такие как '__LINE__' и' __FILE__', поэтому в случае ошибки вы точно знаете, где это происходит. Это невозможно сделать с помощью функции. – tomse

+0

Рассмотрим следующий пример: 'ASSERT (f1() && f2() || f3())' - Я не уверен, будет ли компилятор оптимизировать вызов 'ASSERT' в этом случае и тем не менее fx() - вызовы функций остаются. С пустым макросом ничего не осталось ... – tomse

ответ

2

Преимущество использования макросов для этой цели над функциями, как вы сказали, есть вероятность того, что проверка не будет полностью оптимизирована, и вы по-прежнему будете платить за динамический_cast.

Ваш лучший вариант - использовать assert(dynamic_cast<Derived*>(_ptr) != nullptr). Тип безопасности не покупает вам ничего для поведения, подобного утверждению.

Если вы должны написать свою собственную функцию, вы можете условно позвонить std::abort из заголовка <cstdlib>, но вам придется добавить любую диагностическую информацию самостоятельно.

+0

Да, добавление '! = Nullptr' - это то, что я рассматривал, но оно зависит от того, может ли пользователь добавить его, если это не может привести к неопределенному поведению, поэтому Я хотел попытаться избежать этого. Угадайте, что тогда пользователь должен будет обратить внимание на предупреждения компилятора. – crezefire

+0

Добавление '! = Nullptr' не является обязательным. Результат 'dynamic_cast' будет неявно преобразован в bool и, если результатом будет нулевой указатель, т.е. 'dynamic_cast' не удался, он преобразуется в' false', и assert будет запускаться. Редактировать. Явное добавление проверки нулевого указателя полезно только в том случае, если неявные преобразования делают вас неудобными или если вы хотите, чтобы диагностика была более явной. –