Cv-квалификации prvalues (пересмотренный)
Это продолжение моего предыдущего вопроса, где очевидное согласие заключалось в том, что изменение в обработке cv-квалификаций prvalues было довольно незначительным и несущественным изменением, предназначенным для устранения некоторых несоответствий (например, функции, возвращающие prvalues и объявлено с cv-квалифицированными типами возврата).
Тем не менее, я вижу другое место в стандарте, которое, похоже, полагается на prvalues, имеющие cv-квалифицированные типы: инициализация ссылок const
с prvalues через временное преобразование материализации. Соответствующую формулировку можно найти в нескольких местах в 9.3.3/5
[...] Если преобразованный инициализатор является prvalue, его тип T4 настраивается на тип 'cv1 T4' ([conv.qual]) и применяется временное преобразование материализации ([conv.rval]) [...]
[...] В противном случае выражение инициализатора неявно преобразуется в значение типа 'cv1 T1'. Применяется временное преобразование материализации, и ссылка привязывается к результату.
Намерение, очевидно, состоит в том, чтобы убедиться, что при переходе к фактическому временному преобразованию материализации
7.3.4 Преобразование временной материализации
1 Prvalue типа T может быть преобразовано в xvalue типа T. Это преобразование инициализирует временный объект ([class.teilitary]) типа T из prvalue, оценивая prvalue с временным объектом в качестве его объекта результата. и создает значение x, обозначающее временный объект. [...]
тип T
, который он получает в качестве входных данных, включает необходимые cv-квалификации.
Но как эта cv-квалификация выдерживает 7.2.2/2 в случае не-класса не-массива prvalue?
7.2.2 Тип
2 Если изначально значение prvalue имеет тип 'cv T', где T - неквалифицированный cv некласс, не массив, тип выражения корректируется до T перед любым дальнейшим анализом.
Или это?
Например. какие временные мы получаем в этом примере
const int &r = 42;
Временный const
или нет? Можем ли мы сделать
const_cast<int &>(r) = 101; // Undefined or not?
без запуска неопределенного поведения? Если я не ошибаюсь, первоначальная цель заключалась в получении временного const int
в таких случаях. Это все еще правда? (Для типов классов ответ ясен - мы получаем временный const
.)
Ответы
Ответ 1
Я думаю, что я могу опубликовать здесь ответ от Core отражателя о взаимодействии [dcl.init.ref]/5.3 и [expr.type]/2.
[Dcl.init.ref]/5.3:
Если преобразованный инициализатор является prvalue, его тип T4 настраивается на тип "cv1 T4" ([conv.qual]) и применяется временное преобразование материализации ([conv.rval]).
[Expr.type]/2:
Если изначально значение типа prvalue имеет тип "cv T", где T - неквалифицированный cv некласс, не относящийся к массиву, тип выражения корректируется до T перед любым дальнейшим анализом.
Так что ответ был
Я думаю, что ключевое слово здесь "изначально". Вы корректируете cv-квалификацию один раз, когда изначально формируется prvalue. Любая квалификация cv, добавленная в результате последующих корректировок, не подлежит дальнейшим изменениям.
Итак, const int &r = 42;
приводит к материализации объекта const int
в С++ 17.