Zaawansowane CPP/Ćwiczenia 6: Funkcje typów i inne sztuczki: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
 
(Nie pokazano 11 wersji utworzonych przez 2 użytkowników)
Linia 1: Linia 1:
'''Zadanie 1 '''  Napisać szablon który sprawdza czy jego parametr
+
{{cwiczenie|1||
posiada określony typ stowarzyszony np.:
+
 
 +
Napisz szablon, który sprawdza czy jego parametr
 +
posiada typ stowarzyszony <tt>value_type</tt>, np.:
  
 
  <nowiki> has_value_type<std::vector<int> >::yes</nowiki>
 
  <nowiki> has_value_type<std::vector<int> >::yes</nowiki>
Linia 9: Linia 11:
  
 
wartość <code><nowiki>false</nowiki></code>.  
 
wartość <code><nowiki>false</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">
 +
Można wzorować się na szablonie [[media:Is_class.cpp | is_class]].
 +
</div></div>
 +
 +
<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">
 +
Zasada jest taka sama, jak w przypadku sprawdzania czy dany typ jest klasą. Trzeba tylko wybrać odpowiedni argument pierwszej funkcji testującej. Odpowiednie wyrażenie to <tt>U::value_type</tt>, które nie jest poprawne dla typów <tt>U</tt> nie posiadających stowarzyszonego typu <tt>value_type</tt>. Definiujemy więc:
 +
template<typename U> static one test(typename U::value_type );
 +
 +
Reszta jest jak dla Is_class. Całość kodu jest zamieszczona w pliku [[media:Has_value_type.cpp | has_value_type.cpp]]
 +
</div></div>
  
'''Wskazówka '''  Można wzorować się na szablonie <code><nowiki> is_class</nowiki></code>.
+
{{cwiczenie|2||
 
   
 
   
'''Zadanie 2 '''  Napisać szablon który sprawdza czy jeden z jego
+
Napisz szablon, który sprawdza czy jeden z jego
 
argumentów dziedziczy z drugiego.  
 
argumentów dziedziczy z drugiego.  
 +
}}
 +
<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">
 +
Wskaźnik <code><nowiki>Derived*</nowiki></code> może być konwertowany do <code><nowiki>Base*</nowiki></code> tylko jeśli <code><nowiki>Derived</nowiki></code> dziedziczy z <code><nowiki>Base</nowiki></code> lub <code><nowiki>Base</nowiki></code> jest typem <tt>void</tt>. Można więc wykorzystać szablon <tt>Convertible</tt>.
 +
</div></div>
 +
 +
<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">
 +
Zgodnie ze wskazówką sprawdzamy, korzystając z klasy <tt>Is_convertible</tt>, czy <code><nowiki>Derived*</nowiki></code> może być skonwertowany do <code><nowiki>Base*</nowiki></code> i czy <code><nowiki>Base</nowiki></code> nie równa się <tt>void</tt>:
 +
template<typename Derived, typename Base > struct Is_derived {
 +
    enum {yes = Is_convertible<Derived*,Base*>::yes &&
 +
          !Is_convertible<Base*,void*>::same_type
 +
    };
 +
};
  
'''Wskazówka '''  Jeśli <code><nowiki>Derived</nowiki></code> dziedziczy z <code><nowiki>Base</nowiki></code>
+
Proszę zwrócić uwagę, że porównywane są typy <tt>Base*</tt> i <tt>void*</tt>. Porównanie typów <tt>Base</tt> i <tt>void</tt> za pomocą szablonu <tt>Convertible</tt> nie jest możliwe, bo prowadzi do nielegalnego wyrażenia <tt>test(void)</tt>. Całość kodu jest zawarta w pliku [[media:Derived.cpp | derived.cpp]].
to typ <code><nowiki>Derived *</nowiki></code> może być konwertowany do <code><nowiki>Base *</nowiki></code>.
+
</div></div>
Uwaga, każdy typ wskaźnikowy może być konwertowany do <code><nowiki>void *</nowiki></code>.
 
  
'''Zadanie 3 ''' 
+
{{cwiczenie|3||
Napisać szablon który sprawdza czy dany typ jest wymieniony w podanej
+
 
 +
Napisz szablon, który sprawdza czy dany typ jest wymieniony w podanej
 
liście typów. Np.:
 
liście typów. Np.:
  
Linia 30: Linia 55:
  
 
jest fałszywe.
 
jest fałszywe.
 +
}}
 +
<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">
 +
Idea rozwiązania jest następująca: jeśli nasz podany typ jest głową listy, to wiemy, że należy do listy:
 +
 +
template<typename T, typename Tail> struct In<T,TypeList<T,Tail> >{
 +
    enum {yes=1};
 +
};
 +
 +
Jeśli nie, to sprawdzamy czy należy do ogona:
 +
 +
template<typename T, typename TL> struct In {
 +
    enum {yes=In<T, typename TL::Tail>::yes };
 +
};
  
'''Zadanie 4 ''' 
+
Jeśli dojdziemy do końca listy, czyli do <tt>Null_type</tt>, oznacza to, że szukanego typu nie ma na liście.
  
Implementacja indeksowania listy typów podana na wykładzie, w
+
template<typename T> struct In<T,Null_type> {
przypadku przekroczenia zakresu powuduje bład kompilacji. Napisać
+
    enum {yes=0};
mniej restrykcyjna wersję tego szablonu, która w takiej sytacji "zwraca"  
+
};
 +
 
 +
Kod zawarty jest w pliku [[media:Typelist.h | typelist.h]].
 +
</div></div>
 +
 
 +
{{cwiczenie|4|| 
 +
 
 +
Implementacja indeksowania listy typów podana na wykładzie w
 +
przypadku przekroczenia zakresu powoduje błąd kompilacji. Napisz
 +
mniej restrykcyjną wersję tego szablonu, która w takiej sytacji "zwraca"  
 
typ:
 
typ:
  
 
  <nowiki> struct Empty_type {};</nowiki>
 
  <nowiki> struct Empty_type {};</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">
 +
Rozwiązanie jest podobne jak dla szablonu <tt>At</tt>:
 +
 +
template<int N,typename T> struct At2 {
 +
    typedef typename At2<N-1, typename T::Tail>::Result Result;
 +
};
 +
 +
template<typename H,typename T> struct At2<1,TypeList<H,T> > {
 +
    typedef H Result;
 +
};
 +
 +
Dodajemy tylko specjalizację, która w przypadku napotkania końca listy zwraca <tt> Empty_type</tt>:
 +
 +
template<int N> struct At2<N,Null_type> {
 +
    typedef Empty_type Result;
 +
};
 +
 +
Kod zawarty jest w pliku [[media:Typelist.h | typelist.h]].
 +
</div></div>

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

Ćwiczenie 1

Napisz szablon, który sprawdza czy jego parametr posiada typ stowarzyszony value_type, np.:

 has_value_type<std::vector<int> >::yes

powinno mieć wartość true, a

 has_value_type<int>::yes

wartość false.

Podpowiedź
Rozwiązanie

Ćwiczenie 2

Napisz szablon, który sprawdza czy jeden z jego argumentów dziedziczy z drugiego.

Podpowiedź
Rozwiązanie

Ćwiczenie 3

Napisz szablon, który sprawdza czy dany typ jest wymieniony w podanej liście typów. Np.:

 in<int,TypeList<int,TypeList<double,NullType> >>::yes

jest prawdziwe, a

 in<int,TypeList<char,TypeList<double,NullType> >>::yes

jest fałszywe.

Rozwiązanie

Ćwiczenie 4

Implementacja indeksowania listy typów podana na wykładzie w przypadku przekroczenia zakresu powoduje błąd kompilacji. Napisz mniej restrykcyjną wersję tego szablonu, która w takiej sytacji "zwraca" typ:

 struct Empty_type {};
Rozwiązanie