Try {....} catch (..), только если определенное выражение времени компиляции истинно
Вот что мы пытаемся сделать
try {
std::uninitialized_copy(...);
} catch(...) {
if(!boost::has_trivial_destructor<T>::value) {
// some cleanup to do here...
}
throw;
}
Мы задаемся вопросом, имеет ли значение try/catch стоимость, если константа времени компиляции в if
является ложной.
Может ли компилятор в своих правах "как-если" удалить попытку catch и вести себя как-будто вызов std::uninitialized_copy
появился без try
вокруг него?
Или есть что-то скрытое в спецификациях С++, которое требует, чтобы компилятор оставил его здесь? В качестве примера представьте гипотетическую функцию surrounding_try_blocks()
, которая возвращает динамическое окружение try try, отсчитываемое в настоящее время вокруг кадра.
Ответы
Ответ 1
Я не знаю, что сделает компилятор, но я знаю, что вы можете обеспечить оптимизацию самостоятельно:
template <class T>
typename boost::enable_if_t<boost::has_trivial_destructor<T>::value, void>
wrap_uninitialized_copy (...) {
std::uninitialized_copy(...);
}
template <class T>
typename boost::enable_if_t<!boost::has_trivial_destructor<T>::value, void>
wrap_uninitialized_copy (...) {
try {
std::uninitialized_copy(...);
} catch(...) {
// some cleanup to do here...
throw;
}
}
Ответ 2
Ниже я обобщил стоимость использования исключения, которое я сопоставил из разных источников. Как то, что вы просите в своем втором пункте, мне не очень понятно. Поэтому я подумал, что лучше всего через тебя все. Надеюсь, вы поймете что-то важное.
Чтобы обрабатывать исключения во время выполнения, программы должны выполнять значительную сумму бухгалтерского учета. В каждый момент
они должны иметь возможность идентифицировать объекты, требующие уничтожения, если выбрано исключение; они должны обратить внимание на каждую запись и выйти из блока try; и для каждого блока try они должны отслеживать связанные клаузулы catch и типы исключений, которые могут обрабатывать эти статьи.
Есть вещи, за которые вы платите, даже если вы никогда не используете какие-либо функции обработки исключений. Вы платите за
пространство, используемое структурами данных, необходимое для отслеживания того, какие объекты полностью построены, и
вы платите за время, необходимое для обновления данных данных. Эти затраты обычно довольно скромны.
Тем не менее, программы, скомпилированные без поддержки исключений, как правило, быстрее и меньше, чем их аналоги, скомпилированные с поддержкой исключений
Ответ 3
Из 15.1/8 находим
Выражение-выражение без операндов возвращает текущую обработку исключение (15.3). Исключение возобновляется с использованием существующих временный; не создается новый объект временного исключения...
Для меня это довольно ясно означает, что если предположить, что оценка boost::has_trivial_destructor<T>::value
тривиально может не иметь побочных эффектов, компилятор должен иметь возможность легко определить, что вся основная часть улова не может быть выполнена и что весь конструкцию можно оптимизировать. Я не знаю конкретного компилятора, который делает/не делает этого, однако.
Мое единственное (небольшое) сомнение заключается в том, считает ли язык, что очистка и сброс std::uncaught_exception()
попадают в предложение "как-если".