Рассмотрим фрагмент:
try {
Foo f;
throw std::move(f);
}
catch (Foo& f) { }
[expr.throw] говорит, что:
тип объекта исключения определяется путем удаления любых cv-квалификаторов верхнего уровня из статического типа операнда и корректировки введите "из массива T" или "функция, возвращающая T", в "указатель на T" или "указатель на функцию возврата T", соответственно.
который был бы Foo&&
. Затем объект исключения инициализируется в соответствии с [except.throw]:
Бросание копии исключения инициализирует (8.5, 12.8) временный объект, называемый объектом исключения. временный - это значение lvalue и используется для инициализации переменной, объявленной в соответствующем обработчике (15.3). Если тип объекта исключения будет неполным типом или указателем на неполный тип, отличный от (возможно, cv-qualified)
void
программа плохо сформирована.
Это говорит мне, что объект исключения инициализируется как:
Foo&& __exception_object = std::move(f);
и что обработчик не будет соответствовать. Однако, как gcc, так и clang действительно ловят это исключение. Итак, каков фактический тип объекта исключения здесь? Если Foo
, почему?