2015-09-24 4 views
13

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

try { 
    Foo f; 
    throw std::move(f); 
} 
catch (Foo& f) { } 

[expr.throw] говорит, что:

тип объекта исключения определяется путем удаления верхнего уровня CV-классификаторов из статического типа операнда и отрегулировать тип из «массива Т» или «функции, возвращающей Т», на «указатель на Т» или «указатель на функцию возврата Т», соответственно.

который будет Foo&&. Объект исключения затем инициализируется в соответствии с [except.throw]:

вызов исключения копирования инициализирует (8.5, 12.8) временный объект, называемый объект исключение. Временной значение является значением lvalue и используется для инициализации переменной, указанной в соответствующем обработчике (15.3). Если тип объекта исключения был бы неполным или указателем на неполный тип, отличный от (возможно, cv-qualified) void, программа плохо сформирована.

Это наводит меня на мысль о том, что объект исключения инициализируется как:

Foo&& __exception_object = std::move(f); 

и что обработчик не будет соответствовать. Однако, как gcc, так и clang действительно ловят это исключение. Итак, каков фактический тип объекта исключения здесь? Если Foo, почему?

+5

Почему downvote? – Barry

ответ

14

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

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

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

в первый шаг в этом анализе «программа», чтобы удалить ссылки, см 5 [выражение] р5 и Expressions can have reference type

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

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

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

int& f(); 
throw f(); 

Это бросает int не int&.

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

Смежные вопросы