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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Nie podano opisu zmian
 
Nie podano opisu zmian
 
(Nie pokazano 12 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
''Uwaga: przekonwertowane latex2mediawiki; prawdopodobnie trzeba wprowadzi� poprawki''
{{cwiczenie|1||


{Funkcje typów i inne sztuczki}
Napisz szablon, który sprawdza czy jego parametr
posiada typ stowarzyszony <tt>value_type</tt>, np.:


'''Zadanie 1 ''' Napisać szablon który sprawdza czy jego parametr
  <nowiki> has_value_type<std::vector<int> >::yes</nowiki>
posiada określony typ stowarzyszony np.:


<nowiki> has_value_type<std::vector<int> >::yes
powinno mieć wartość <code><nowiki>true</nowiki></code>, a
</nowiki>


powinno mieć wartość <code><nowiki> true</nowiki></code>, a
<nowiki> has_value_type<int>::yes</nowiki>


<nowiki> has_value_type<int>::yes
wartość <code><nowiki>false</nowiki></code>.
</nowiki>
}}
<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>


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">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 );


'''Wskazówka '''  Można wzorować się na szablonie <code><nowiki> is_class</nowiki></code>.
Reszta jest jak dla Is_class. Całość kodu jest zamieszczona w pliku [[media:Has_value_type.cpp | has_value_type.cpp]]
</div></div>
 
{{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.:


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


jest prawdziwe, a  
jest prawdziwe, a  


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


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};
};


'''Zadanie 4 ''' 
Jeśli nie, to sprawdzamy czy należy do ogona:


Implementacja indeksowania listy typów podana na wykładzie, w
template<typename T, typename TL> struct In {
przypadku przekroczenia zakresu powuduje bład kompilacji. Napisać
    enum {yes=In<T, typename TL::Tail>::yes };
mniej restrykcyjna wersję tego szablonu, która w takiej sytacji "zwraca"  
};
 
Jeśli dojdziemy do końca listy, czyli do <tt>Null_type</tt>, oznacza to, że szukanego typu nie ma na liście.
 
template<typename T> struct In<T,Null_type> {
    enum {yes=0};
};
 
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> struct Empty_type {};</nowiki>
</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