Есть ли причина использовать утверждение времени выполнения вместо утверждения времени компиляции?

Изучая кодовую базу Visual C ++, я обнаружил следующую странную вещь. Утверждение времени выполнения (то есть проверка условия и выдача исключения, если условие нарушается) использовалось в случае, когда условие могло быть оценено во время компиляции:

assert( sizeof( SomeType ) == sizeof( SomeOtherType ) );

очевидно, что компилятор оценит условие и заменит код, который будет либо

assert( true );

который ничего не делает или

assert( false );

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

IMO следует использовать assert во время компиляции по следующим причинам:

  • он обнаружил бы нарушение условия раньше - во время компиляции - и
  • это позволит испускать более чистый (а значит, более быстрый и меньший) машинный код

Похоже, что утверждение во время компиляции - единственное правильное решение. Есть ли какая-то возможная причина предпочесть здесь утверждение времени выполнения?


person sharptooth    schedule 07.09.2010    source источник
comment
assert обычно не генерирует исключение, а прерывает выполнение программы.   -  person David Rodríguez - dribeas    schedule 07.09.2010
comment
На данный момент нет стандартного утверждения времени компиляции. Этот факт очень важен, особенно для старых кодовых баз.   -  person Dennis Zickefoose    schedule 07.09.2010
comment
В частности, VC6 имеет всевозможные специальные коды случаев во всех библиотеках Boost. Если ваш код сейчас или когда-либо был скомпилирован VC6 (и можно предположить, что это верно для большей части собственного исходного кода MS), по крайней мере BOOST_STATIC_ASSERT, вероятно, не может быть и речи.   -  person Dennis Zickefoose    schedule 07.09.2010
comment
Большинство asserts () компилируются с нулевыми операциями в выпуске. Они активны только в отладке (т. Е. В тестовом коде).   -  person Martin York    schedule 07.09.2010


Ответы (2)


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

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

В C ++ 0x встроенная функция static_assert должна прекратить все основания для использования утверждения времени выполнения, когда будет работать утверждение времени компиляции.

person GManNickG    schedule 07.09.2010

Мы не можем сказать без контекста. В коде шаблона некоторые ветки могут быть недоступны для некоторых экземпляров. Утверждение во время компиляции было бы неуместным, так как оно искажает форму всей функции. assert(<type-dependent expression>) - нет.

E.g.

template <typename T> void foo(T t)
{
  if (t < 0) {
    assert(std::numeric_limits<T>::min() < 0);
    T u = t - std::numeric_limits<T>::min();
  }
}

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

person MSalters    schedule 07.09.2010
comment
Почему нельзя сделать static_assert? - person GManNickG; 07.09.2010
comment
assert(std::numeric_limits<T>::min < 0); всегда выходит из строя, независимо от T. - person usta; 07.09.2010
comment
@usta: вы комментируете отсутствие вызова функции? @MSalters: Я думаю, ты хотел min() - person Dennis Zickefoose; 07.09.2010
comment
@Dennis Zickefoose Да, я комментирую отсутствие (). С его добавлением это assert по-прежнему не может быть превращено в статическое assert, потому что std :: numeric_limits ‹T› :: min () не является (пока) выражением времени компиляции. - person usta; 07.09.2010
comment
Исправлено отсутствующее (). @Gman: потому что static_assert остановит компиляцию foo<unsigned int>. - person MSalters; 08.09.2010