Допустимо ли приводить не-классное не-массивное prvalue к cv-квалифицированному типу?

Я читал о категориях значений и натолкнулся на следующее (для краткости многое опущено):

Следующие выражения являются выражениями prvalue:

  • литерал (кроме строкового литерала), такой как 42, true или nullptr;

Свойства:

  • Некваливный prvalue, не являющийся массивом, не может быть квалифицирован cv.

Но... следующая программа компилируется и прекрасно работает на ideone.com и с g++ 5.4.0:

#include <iostream>

int main() {
    std::cout << ((const int) 42) << std::endl;
}

Я понимаю, что компиляторы предоставляют расширения и могут выполнять любые действия, если задано неопределенное поведение. Я просто пытаюсь понять, что стандартные мандаты.

В N4296 я нашел следующее к соответствующему отрывку:

[выражение]

[... содержимое пропущено... ]

  1. Если значение prvalue изначально имеет тип "cv T", где T - неквалифицированный cv некласс, не массив, тип выражения корректируется до T перед любым дальнейшим анализом.

Термин "изначально" это то, что бросает меня. Не ясно, разрешено ли это как результат другого выражения, такого как пользователь для явного приведения не-класса prvalue, не являющегося массивом, к cv-квалифицированному типу (который дает другое значение prvalue), или это применяется только к "root" "выражение (42 в этом случае).

У меня вопрос: разрешает ли стандарт такие выражения (который просто удаляет cv-квалификаторы), или это запрещено (и, если необходимо, где это требуется)?

2 ответа

Решение

Спасибо SanderDeDycker за указание на соответствующую часть стандарта для поиска.

На мой вопрос ответили в следующем разделе N4296 (выделено мной):

[expr.cast]

  1. Результат выражения (T) cast-expression имеет тип T . Результатом является lvalue, если T является ссылочным типом lvalue или ссылкой rvalue на тип функции, и xvalue, если T является ссылкой rvalue на тип объекта; в противном случае результат является prvalue. [Примечание: если T является неклассовым типом, который квалифицирован cv, то квалификаторы cv отбрасываются при определении типа результирующего значения prvalue; см. пункт 5. - примечание к концу]

Таким образом, мы можем сделать вывод, что такие выражения, как (const int) 42 совершенно легальны C++.

Вы должны знать, что cppreference не является нормативным. "Cannot" может быть прочитано двумя способами:

  • Это запрещено, аля "не будет"

  • Это просто не может произойти, аля инварианты

Цитата, которую вы перечислили в тексте:

Если значение prvalue изначально имеет тип "cv T", где T - неквалифицированный cv некласс, не массив, тип выражения корректируется до T перед любым дальнейшим анализом.

предлагает мне, что квалифицированное CV-значение отбрасывает квалификации так же, как массивы могут распадаться на указатели (чтобы уточнить, это правило не происходит в тот момент, когда приведение будет неправильно сформировано). Дефект #1261 делает язык довольно явным о том, что и где происходит.

Другие вопросы по тегам