Подтвердить что ты не робот

Выбрасывание rvalue

Рассмотрим фрагмент:

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, почему?

4b9b3361

Ответ 1

Статический тип выражения никогда не является ссылочным типом.

1.3.24 [defns.static.type] определяет "статический тип":

тип выражения (3.9), полученный в результате анализа программы без рассмотрения семантики выполнения

первый шаг в том, что "анализ программы" заключается в удалении ссылок, см. 5 [expr] p5 и Выражения могут иметь ссылочный тип

Если выражение первоначально имеет тип "ссылка на T" (8.3.2, 8.5.3), тип доводится до T до любого дальнейшего анализа. Выражение обозначает объект или функцию, обозначенные ссылкой, а выражение представляет собой значение lvalue или значение x, в зависимости от выражения.

So std::move(f) - это выражение xvalue со статическим типом Foo.

Вам не нужно включать rvalues, чтобы продемонстрировать это, то же самое было в С++ 03 с помощью:

int& f();
throw f();

Это выдает a int не a int&.

Без учета специфики объект исключения является объектом, а ссылка не является объектом, поэтому объект исключения не может быть ссылкой. Это должен быть объект.