Почему decltype удаляет const из возвращаемых типов для встроенных типов?

Как правило, decltype сохраняет константу:

const int ci = 0;
decltype(ci)  x;         // x is const int
x = 5;                   // error--x is const

class Gadget{}:

const Gadget makeCG();         // factory

decltype(makeCG()) y1, y2;     // y1 and y2 are const Gadgets
y1 = y2;                       // error--y1 is const

Но для возвращаемых типов const, которые возвращают фундаментальные типы, decltype, похоже, отбрасывает const:

const int makeCI();            // factory

decltype(makeCI()) z;          // z is NOT const
z = 5;                         // okay

Почему decltype отказывается от константности в этом случае? Я имею в виду два вопроса:

  1. Какая часть стандарта определяет такое поведение?
  2. Какова мотивация для определения поведения таким образом?

Спасибо.


person KnowItAllWannabe    schedule 29.08.2013    source источник
comment
С какой стати вы хотите вернуть значение const?   -  person Billy ONeal    schedule 29.08.2013
comment
@BillyONeal: Хороший вопрос, но это не делает его недействительным.   -  person Nicol Bolas    schedule 29.08.2013
comment
@NicolBolas: я никогда не утверждал, что это так.   -  person Billy ONeal    schedule 29.08.2013
comment
@BillyONeal: Меня интересует понимание decltype, и поскольку он по-разному обрабатывает возврат по значению для определяемых пользователем и фундаментальных типов, я просто хотел бы знать, почему.   -  person KnowItAllWannabe    schedule 29.08.2013


Ответы (1)


Поведение, которое вы наблюдаете, правильное: decltype(makeCI()) это int, а не int const.

Выражение вызова функции makeCI() является выражением prvalue. Согласно С++ 11 §3.10 [basic.lval]/4:

prvalue класса может иметь типы с квалификацией cv; значения prvalue, не относящиеся к классу, всегда имеют типы cv-unqualified.

Термин "cv-qualification" относится к const- и volatile-квалификации. int не является типом класса, поэтому тип выражения rvalue makeCI() равен int и не является константным.

(В недавних проектах стандарта языка C++, например, N3690, этот текст был удален и заменен новым текстом в §5 [expr]/6, в котором говорится: «Если prvalue изначально имеет тип «cv T», где T является cv-неквалифицированным типом, не относящимся к классу и массиву, тип выражения корректируется до T перед любым дальнейшим анализом». См. дефект CWG 1261 для получения подробной информации.)

person James McNellis    schedule 29.08.2013
comment
Мне действительно нужно уделять больше внимания, я думаю. +1. - person Billy ONeal; 29.08.2013
comment
Спасибо за указание на часть стандарта, в которой рассматривается этот вопрос. Есть понимание мотивации? - person KnowItAllWannabe; 29.08.2013
comment
Я не знаю историю этого правила. Это правило присутствует в C++98. В большинстве случаев это не имеет значения. (Например, для большинства встроенных операций требуется модифицируемое lvalue, где происходит модификация, поэтому константная квалификация выражений rvalue не имеет значения.) - person James McNellis; 29.08.2013