Cv-квалификация prvalues ​​в С++ 14

Похоже, что С++ 11 и С++ 14 рассматривают cv-квалификацию prvalues ​​по-разному.

С++ 11 придерживается "классического" подхода, который существует со времен С++ 98: согласно 3.10/4 "неклассовые prvalues ​​всегда имеют cv-неквалифицированные типы".

С++ 14 содержит аналогичную формулировку в 3.10/4, но она представлена ​​в виде примечания: "[Замечание: классы и массивы prvalues ​​могут иметь типы cv-qual, другие prvalues ​​всегда имеют cv-неквалифицированные типы. 5. -end note]"

И в разделе 5 говорится:

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

Эта запись 5/6 является новой в С++ 14. Теперь он рассматривает cv-квалификацию prvalues, используя тот же подход, который всегда использовался с результатами ссылочного типа (см. 5/5).

Что может быть причиной этого изменения? С++ 11 и до того, как запретить неклассовые знаки права иметь любую cv-квалификацию. С++ 14 говорит, что неклассические, non-array prvalues ​​могут иметь cv-квалификацию, но эти cv-квалификации отбрасываются перед любым дальнейшим анализом.

Мое предположение было бы в том, что есть некоторые новые (для С++ 14) языковые особенности, которые могут как-то "видеть" cv-квалификацию prvalues ​​при правильных обстоятельствах (до того, как будет выполнена вышеупомянутая корректировка). Они существуют? И если да, то каковы эти функции? 2


Вопрос возник из следующего контекста: представьте себе компилятор, который внутренне реализует скрытый параметр this класса X как переменную типа X *const. Поскольку компилятор должен выставлять this как prvalue, то const не должен приводить к каким-либо проблемам в С++ 11 (или раньше), где скалярные prvalues ​​никогда не имеют квалификацию cv. Но как насчет С++ 14? Если тот же самый компилятор предоставляет this как значение типа X *const, может ли это привести к проблемам?


1 По-видимому, существует противоречие между 5/6 и примечанием в 3.10/4 в С++ 14, но заметки в любом случае не являются нормативными. И я использую черновик текста.

2 Мое первоначальное предположение было decltype. И я даже подумал, что нашел ответ, когда попытался

std::cout << std::is_same<decltype((const int) 0), const int>::value << std::endl;

в GCC, который выводит 1. Однако, видя, что Clang и VС++ вывод 0 (и что спецификация decltype, похоже, не поддерживает это поведение), я склонен полагать, что это всего лишь ошибка в GCC (начиная с 6.1)

Ответы

Ответ 1

В соответствии с commit на github это было сделано для решения CWG1261: Явная обработка CV-квалификации с неклассовыми значениями

Основываясь на комментариях к вопросу, кажется, что есть место для неожиданных изменений в категории типов this (формально prvalue) и что gcc ранее, и вместо этого MSVC вместо этого использовал const lvalue.

Формулировка подтягивает отверстие так, что, например, даже если this по какой-то манере компилятора - это значение класса X* const, перед любым дальнейшим анализом оно настраивается на X*.

Аналогично, ваш данный пример выглядит как ошибка gcc. Возможно, decltype не рассматривает тип значения перед применением c-style cast.

В настоящее время примечание в [basic.lval]/4 заключается в том, что теперь это следствие нового текста в [expr]/6, а не для указания правила в [basic.lval]/4.

Полный кредит TC за то, что он в основном ответил на это в комментариях к вопросу, включая ссылку на gcc-fix и другие другие примеры ранее -специфическое поведение для cv-квалифицированных неклассифицированных значений без массива.