Zaawansowane CPP/Ćwiczenia 5: Klasy cech: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
 
 
(Nie pokazano 11 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
 +
W poprzednich rozdziałach przedstawiono mechanizm typów związanych
 +
(czyli typedefów zagnieżdżonych wewnątrz klasy).
 +
Jest on intensywnie wykorzystywany w STL, gdzie bardzo przydaje się
 +
do pisania szablonów funkcji parametryzowanych typem iteratora (albo
 +
pojemnika).
 +
Zagnieżdżony wewnątrz tego typu typ związany <code><nowiki>value_type</nowiki></code> pozwala na
 +
tworzenie pomocniczych zmiennych, przechowujących przetwarzane wartości,
 +
<code><nowiki>iterator_category</nowiki></code>  pozwala wybrać odpowiednią wersję kodu,
 +
i tak dalej.
  
''Uwaga: przekonwertowane latex2mediawiki; prawdopodobnie trzeba wprowadzi� poprawki''
+
Technika typów związanych ma jednak dwie wady.
 +
Po pierwsze, muszą być one podczepione pod klasę, a czasem możemy chcieć
 +
uzyskać informacje na temat czegoś, co może być albo klasą, albo prostym
 +
typem wbudowanym (patrz iteratory - albo klasy, albo zwykłe wskaźniki).
 +
Po drugie, lista przekazywanych informacji jest zamknięta; aby
 +
coś dodać, trzeba mieć dostęp do kodu źródłowego i go zmodyfikować.
 +
Rozwiązaniem obu problemów są szablony cechujące.
  
{Funkcje typów i inne sztuczki}
+
{{cwiczenie|1||
 +
 +
Zaimplementuj funkcję uogólnioną biorącą jako argumenty parę iteratorów
 +
i zwracającą najmniejszy z tego ciągu elementów.
 +
Najpierw opracuj wersję wykorzystującą typ związany, a potem wersję
 +
korzystającą ze standardowego szablonu cechującego <code><nowiki>iterator_traits</nowiki></code>.
 +
Sprawdź działanie obu wersji na liście oraz na zwykłej tablicy.
 +
Przypominajka: w obu przypadkach niezbędne będzie słówko kluczowe
 +
<code><nowiki>typename</nowiki></code>.
 +
}}
 +
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
 +
Patrz plik [[media:Najmniejszy.cpp | najmniejszy.cpp]].
 +
</div></div>
  
'''Zadanie 1 ''' Napisać szablon który sprawdza czy jego parametr
+
{{cwiczenie|2||
posiada określony typ stowarzyszony np.:
+
   
 
+
Zapoznaj się z plikiem [[media:Kategorie.cpp | kategorie.cpp]].
<nowiki> has_value_type<std::vector<int> >::yes
+
Jest w nim przedstawiony sposób selekcji jednej spośród kilku implementacji
</nowiki>
+
algorytmu na podstawie możliwości oferowanych przez przekazany iterator;
 
+
w tym konkretnym przykładzie rozróżniamy dwie grupy: iteratory o swobodnym
powinno mieć wartość <code><nowiki> true</nowiki></code>, a
+
dostępie oraz wszystkie inne.
 
+
Rozszerz kod tak, aby wybierana była jedna z trzech możliwości: swobodny
<nowiki> has_value_type<int>::yes
+
dostęp, dwukierunkowe, gorsze niż dwukierunkowe.
</nowiki>
+
}}
 
+
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
wartość <code><nowiki> false</nowiki></code>.
+
Patrz plik [[media:Kategorie_rozw.cpp | kategorie_rozw.cpp]].
 +
</div></div>
  
'''Wskazówka '''  Można wzorować się na szablonie <code><nowiki> is_class</nowiki></code>.
+
{{cwiczenie|3||
 
   
 
   
'''Zadanie 2 '''  Napisać szablon który sprawdza czy jeden z jego
+
Opierając się na przykładowym kodzie z poprzedniego zadania zaimplementuj
argumentów dziedziczy z drugiego.  
+
wariantowy algorytm sortowania ciągów.
 
+
Dla iteratorów jednokierunkowych użyj sortowania przez prosty wybór (patrz
'''Wskazówka '''  Jeśli <code><nowiki> Derived</nowiki></code> dziedziczy z <code><nowiki> Base</nowiki></code>
+
odpowiednie ćwiczenie w [[Zaawansowane CPP/Ćwiczenia 3: Szablony II|ćwiczeniach do wykładu 3]]);
to typ <code><nowiki> Derived *</nowiki></code> może być konwertowany do <code><nowiki> Base *</nowiki></code>.
+
dla tych o dostępie swobodnym użyj quicksortu.
Uwaga, każdy typ wskaźnikowy może być konwertowany do <code><nowiki> void *</nowiki></code>.
+
}}
 
+
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">
'''Zadanie 3 ''' 
+
Patrz plik [[media:Sortowania.cpp | sortowania.cpp]].
Napisać szablon który sprawdza czy dany typ jest wymieniony w podanej
+
</div></div>
liście typów. Np.:
 
 
 
<nowiki> in<int,TypeList<int,TypeList<double,NullType> >>::yes
 
</nowiki>
 
 
 
jest prawdziwe, a
 
 
 
<nowiki> in<int,TypeList<char,TypeList<double,NullType> >>::yes
 
</nowiki>
 
 
 
jest fałszywe.
 
  
'''Zadanie 4 ''' 
+
{{cwiczenie|4||
  
Implementacja indeksowania listy typów podana na wykładzie, w
+
Do jakichś bliżej nie znanych celów potrzebny jest sposób na odróżnianie
przypadku przekroczenia zakresu powuduje bład kompilacji. Napisać
+
iteratorów będących zwykłymi, klasycznymi wskaźnikami od wszystkich
mniej restrykcyjna wersję tego szablonu, która w takiej sytacji "zwraca"  
+
pozostałych.
typ:
+
Ponieważ biblioteka standardowa nie dostarcza odpowiedniego mechanizmu,
 +
trzeba go samodzielnie stworzyć.
 +
Zaimplementuj szablon cechujący o nazwie <code><nowiki>is_pointer</nowiki></code>, zawierający
 +
składową boolowską <code><nowiki>value</nowiki></code> .
 +
}}
 +
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Podpowiedź</span><div class="mw-collapsible-content" style="display:none">
 +
Stwórz ogólny szablon zawsze zwracający <code><nowiki>false</nowiki></code>, a potem wyspecjalizuj go dla typów będących wskaźnikiem do czegoś i tam zwracaj <code><nowiki>true</nowiki></code>.
 +
</div></div>
  
<nowiki> struct Empty_type {};
+
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span><div class="mw-collapsible-content" style="display:none">  
</nowiki>
+
Patrz plik [[media:Czy_wsk.cpp | czy_wsk.cpp]].
 +
</div></div>

Aktualna wersja na dzień 10:29, 2 paź 2006

W poprzednich rozdziałach przedstawiono mechanizm typów związanych (czyli typedefów zagnieżdżonych wewnątrz klasy). Jest on intensywnie wykorzystywany w STL, gdzie bardzo przydaje się do pisania szablonów funkcji parametryzowanych typem iteratora (albo pojemnika). Zagnieżdżony wewnątrz tego typu typ związany value_type pozwala na tworzenie pomocniczych zmiennych, przechowujących przetwarzane wartości, iterator_category pozwala wybrać odpowiednią wersję kodu, i tak dalej.

Technika typów związanych ma jednak dwie wady. Po pierwsze, muszą być one podczepione pod klasę, a czasem możemy chcieć uzyskać informacje na temat czegoś, co może być albo klasą, albo prostym typem wbudowanym (patrz iteratory - albo klasy, albo zwykłe wskaźniki). Po drugie, lista przekazywanych informacji jest zamknięta; aby coś dodać, trzeba mieć dostęp do kodu źródłowego i go zmodyfikować. Rozwiązaniem obu problemów są szablony cechujące.

Ćwiczenie 1

Zaimplementuj funkcję uogólnioną biorącą jako argumenty parę iteratorów i zwracającą najmniejszy z tego ciągu elementów. Najpierw opracuj wersję wykorzystującą typ związany, a potem wersję korzystającą ze standardowego szablonu cechującego iterator_traits. Sprawdź działanie obu wersji na liście oraz na zwykłej tablicy. Przypominajka: w obu przypadkach niezbędne będzie słówko kluczowe typename.

Rozwiązanie

Ćwiczenie 2

Zapoznaj się z plikiem kategorie.cpp. Jest w nim przedstawiony sposób selekcji jednej spośród kilku implementacji algorytmu na podstawie możliwości oferowanych przez przekazany iterator; w tym konkretnym przykładzie rozróżniamy dwie grupy: iteratory o swobodnym dostępie oraz wszystkie inne. Rozszerz kod tak, aby wybierana była jedna z trzech możliwości: swobodny dostęp, dwukierunkowe, gorsze niż dwukierunkowe.

Rozwiązanie

Ćwiczenie 3

Opierając się na przykładowym kodzie z poprzedniego zadania zaimplementuj wariantowy algorytm sortowania ciągów. Dla iteratorów jednokierunkowych użyj sortowania przez prosty wybór (patrz odpowiednie ćwiczenie w ćwiczeniach do wykładu 3); dla tych o dostępie swobodnym użyj quicksortu.

Rozwiązanie

Ćwiczenie 4

Do jakichś bliżej nie znanych celów potrzebny jest sposób na odróżnianie iteratorów będących zwykłymi, klasycznymi wskaźnikami od wszystkich pozostałych. Ponieważ biblioteka standardowa nie dostarcza odpowiedniego mechanizmu, trzeba go samodzielnie stworzyć. Zaimplementuj szablon cechujący o nazwie is_pointer, zawierający składową boolowską value .

Podpowiedź
Rozwiązanie