2014-09-28 10 views
5

z C++ projekt normy N3337:Dlaczego zachowanie decltype jest zdefiniowane tak, jak jest?

7.1.6.2 Proste Specyfikatory typu

4 typu oznaczone decltype(e) jest zdefiniowany w następujący sposób:

- jeśli e jest unparenthesized id- wyrażenie lub niepasteryzowany dostęp do klasy (5.2.5), decltype(e) jest typem jednostki o nazwie e. Jeśli nie ma takiego obiektu lub jeśli e nazywa zestaw przeciążonych funkcji, program jest źle sformułowany;

- w przeciwnym razie, jeśli e jest wartością x, to decltype(e) jest T&&, gdzie T jest typem e;

- w przeciwnym razie, jeżeli E jest lwartością, decltype(e) jest T& gdzie T jest typu e;

Jeśli rozumiem powyższe prawidłowo,

int a; 
decltype(a) b = 10; // type of b is int 

int* ap; 
decltype(*ap) c = 10; // Does not work since type of c is int& 

Czy możesz wyjaśnić, czy punkt do jakiejś dokumentacji, która wyjaśnia, dlaczego decltype(*ap) nie mogło być po prostu int?

+0

Zakładam, że już wiesz :), ale dla rekordu możesz to zmienić, używając 'std :: remove_reference' lub' std :: remove_pointer'. – 101010

+0

@ 40two, tak, znam te narzędzia. Próbuję zrozumieć, dlaczego język jest zdefiniowany tak, jak jest. –

+0

Wiedziałem, że znasz to, ponieważ jesteś zwykłym podejrzanym w tych lokalach. Głównym powodem, dla którego mogę myśleć, jest użycie "decltype" w zwrocie powrotu. Usunięcie '&' z typu byłoby niewygodne w podejściu powrotnym. – 101010

Odpowiedz

6

Wysiłek standaryzacyjny z decltype był herkulesowym wysiłkiem obejmującym wiele lat. Było 7 wersji tego artykułu, zanim komisja ostatecznie go zaakceptowała. Wersje były:

ciekawe, nasiona zachowania których mowa, są w pierwszej rewizji: N1478, która wprowadza konieczność „dwóch rodzajów typeof. Albo w celu zachowania lub spadać odwołań w rodzaju”

Ten papier idzie dać uzasadnienie dla wariantu odniesienia do konserwacji, w tym ten cytat:

Z drugiej strony, semantyka referencyjne upuszczanie nie dostarcza mechanizm dokładnie wyrażając powrót typy ogólnych funkcji , jak wykazał Strouscutrup [Str02]. To implikuje, że , który upuszczałby literę referencyjną, powodowałoby problemy dla autorów bibliotek generycznych .

Nie ma substytutu do czytania w tych dokumentach. Jednak można podsumować, że decltype służy dwóm celom:

  1. Aby zgłosić zadeklarowany typ identyfikatora.
  2. Aby zgłosić typ wyrażenia.

Dla drugiego przypadku użycia przypomnij, że wyrażenia nie są typami odniesienia, ale zamiast tego są jedną z wartości l, xvalue lub prvalues. Zgodnie z konwencją, gdy decltype zgłasza typ wyrażenia lwartości, powoduje, że typ jest referencją o wartości l, a gdy wyrażenie jest wartością x, raportowany typ staje się referencją rwartości.

W twoim przykładzie *ap jest wyrażeniem, podczas gdy a jest identyfikatorem. Tak więc twój przykład wykorzystuje oba przypadki użycia, jak po raz pierwszy wprowadzono w N1478.

Należy również pamiętać, że decltype nie został zaprojektowany w izolacji. Reszta języka C++ ewoluowała w tym okresie czasu (na przykład odniesienia rvalue), a projekt decltype został powtórzony, aby dotrzymać kroku.

Należy również zauważyć, że po przyjęciu propozycji decltype, kontynuowała ona (i trwa do dnia dzisiejszego) ewoluowanie. Zobacz tę listę zagadnień:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_index.html

konkretnie punkt 7.1.6.2 (co jest sekcja gdzie większość specyfikacji życiu decltype).