Я читал на категории значений, и наткнулся на следующее (для краткости многое опущено):
Следующие выражения являются выражениями prvalue:
- литерал (кроме строкового литерала), такой как 42, true или nullptr;
Свойства:
- Некваливный prvalue, не являющийся массивом, не может быть квалифицирован cv.
Но … следующая программа компилируется и работает нормально на ideone.com и с g ++ 5.4.0:
#include <iostream>
int main() {
std::cout << ((const int) 42) << std::endl;
}
Я понимаю, что компиляторы предоставляют расширения и могут выполнять любые действия, если задано неопределенное поведение. Я просто пытаюсь понять, что стандартные мандаты.
В N4296, Я нашел следующее в соответствующем отрывке:
[Выражение]
[… содержимое пропущено …]
- Если значение изначально имеет тип «cv T», где T представляет собой
cv-неквалифицированный некласс, тип не массив, тип выражения
корректируется до Т перед любым дальнейшим анализом.
Термин «изначально» это то, что бросает меня. Не ясно, разрешено ли это как результат другого выражения, такого как пользователь для явного приведения не-класса prvalue, не являющегося массивом, к cv-квалифицированному типу (который дает другое значение prvalue), или это применяется только к «root» «выражение (42
в этом случае).
У меня вопрос: разрешает ли стандарт такие выражения (который просто удаляет cv-квалификаторы), или это запрещено (и, если необходимо, где это требуется)?
Вы должны знать, что cppreference не является нормативным. «Cannot» может быть прочитано двумя способами:
Это запрещено, аля «не будет»
Это просто не может произойти, аля инварианты
Цитата, которую вы перечислили в тексте:
Если значение изначально имеет тип «cv T», где T представляет собой
cv-неквалифицированный некласс, тип не массив, тип выражения
корректируется до Т перед любым дальнейшим анализом.
предлагает мне, что квалифицированное CV-значение отбрасывает квалификации так же, как массивы могут распадаться на указатели (чтобы уточнить, это правило не происходит в тот момент, когда приведение будет неправильно сформировано). дефект # 1261 действительно делает язык довольно явным о том, что и где происходит.
Спасибо SanderDeDycker за указание на соответствующую часть стандарта для поиска.
На мой вопрос ответили в следующем разделе N4296 (выделение мое):
[Expr.cast]
- Результат выражения (T) cast-expression имеет тип T.
результатом является lvalue, если T является ссылочным типом lvalue или rvalue
ссылка на тип функции и значение xvalue, если T является ссылкой rvalue
типу объекта; в противном случае результат является prvalue. [Примечание: если T является
неклассный тип, который является cv-квалифицированным, cv-квалификаторы отбрасываются
при определении типа полученного значения; см. пункт 5. —
конечная нота]
Таким образом, мы можем сделать вывод, что такие выражения, как (const int) 42
совершенно легальны C ++.