Выбросить временный аргумент, переданный по ссылке

inline void my_assert( bool cond, const std::exception &e = my_assert_failed() ) 
{ 
    if ( !cond ) 
      throw e;
}

Стандарт гарантирует, что:

Временная привязка к эталонному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.

И для брошенного временного объекта:

Временное сохранение сохраняется до тех пор, пока выполняется обработчик для этого исключения.

Могу ли я сделать вывод о том, что временное, которое передается в my_assert, сохраняется до тех пор, пока блок catch не завершится?

Ответы

Ответ 1

Из N4296 (первый черновик после финального С++ 14) [15.1p3]:

Бросание копии исключения инициализирует (8.5, 12.8) временный объект, называемый объектом исключения. Временной является значением lvalue и используется для инициализации переменной, объявленной в соответствующем обработчике (15.3).

Поэтому вы не можете предположить, что ваш временный "выживает бросок". Если вы выбрали, конструктор копирования объекта исключения типа std::exception будет вызываться с e в качестве аргумента. Временное ограничение e будет уничтожено, когда управление оставляет полное выражение, содержащее вызов my_assert (либо после нормального возврата, либо как часть разворачивания стека, поскольку вы условно выбрасываете исключение).

Есть обстоятельства, когда копирование объекта исключения может быть отменено, но это не один из них, согласно [12.8p31.2]:

- в выражении throw (5.17), когда операнд - это имя энергонезависимый автоматический объект (кроме функции или catch-clause параметр), объем которого не выходит за пределы самого внутреннего включающий try-block (если есть), операция копирования/перемещения из операнд к объекту исключения (15.1) может быть опущен построение автоматического объекта непосредственно в объект исключения

(акцент мой)