2013-08-29 15 views
8

Zgodnie z ogólną zasadą, decltype zachowuje constness:Dlaczego decltype usuwa const z typów zwracanych dla typów wbudowanych?

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 

Ale dla typów const zwrotnych, które zwracają podstawowe typy, decltype zdaje się rzucać const dala:

const int makeCI();   // factory 

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

Dlaczego decltype odrzuconych constness w tym przypadku ? Mam na myśli pytanie na dwa sposoby:

  1. Jaka część standardu określa to zachowanie?
  2. Jaka jest motywacja do określania zachowania w ten sposób?

Dzięki.

+2

Dlaczego, na Boga, chciałbyś return by const value? –

+0

@BillyONeal: Dobre pytanie, ale to nie unieważnia tego. –

+0

@NicolBolas: Nigdy nie twierdziłem, że tak. –

Odpowiedz

16

Zachowanie, które obserwujesz, jest poprawne: decltype(makeCI()) to int, a nie int const.

Wyrażenie funkcji wywołania makeCI() jest wyrażeniem prvalue. Zgodnie z C++ 11 §3.10 [basic.lval]/4:

Prv klasy mogą mieć kwalifikacje cv; prvalues ​​pozaklasowe zawsze mają typy niekwalifikujące się do cv.

Termin "kwalifikacja cv" odnosi się do kwalifikacji const i volatile. int nie jest typem klasy, więc typ wyrażenia rvalue makeCI() jest int i nie jest const-kwalifikowany.

(W ostatnich wersjach standardu języka C++, np. N3690, tekst ten został usunięty i zastąpiony nowym tekstem w §5 [wyrażenie]/6, który stwierdza: "Jeśli wartość prinalue ma początkowo typ" cv T , "gdzie T jest nieklajnalnym niekwalifiktowanym, nieklazycznym, nie macierzowym typem, typ ekspresji jest dostosowywany do T przed jakąkolwiek dalszą analizą." Szczegóły patrz CWG defect 1261).

+0

Naprawdę muszę zwrócić większą uwagę, myślę. +1. –

+0

Dzięki za wskaźnik do części normy, która odpowiada na to pytanie. Jaki wgląd w motywację? – KnowItAllWannabe

+0

Nie znam historii tej reguły. Ta reguła jest obecna w C++ 98. W większości przypadków nie ma to znaczenia. (Np. Większość wbudowanych operacji wymaga modyfikowalnej wartości l, w której zachodzi modyfikacja, więc const-kwalifikacja wyrażeń rvalue nie ma znaczenia.) –

Powiązane problemy