Zaawansowane CPP/Ćwiczenia 9: Szablony wyrażeń: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Mirek (dyskusja | edycje)
Nie podano opisu zmian
Mirek (dyskusja | edycje)
Nie podano opisu zmian
Linia 52: Linia 52:
}}
}}
<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">
<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">
Implementujemy rekurencyjną definicję potęgi:
Rozwiązanie jest całkowicie analogiczne do szblonów wyrażeń podanych na wykładzie. Zaczynamy od klas reprezentujących odpowiednio pierwszy, drugi i trzeci argument wyrażenia logicznego:
<center><math>\displaystyle
N^M=N*N^{M-1},\quad N^0=1
</math></center>


  template<size_t N,size_t M> struct pow {
  struct First {
     enum {val=N*pow<N,M-1>::val};
    bool operator()(bool q) {return q;};
  };<br>
    bool operator()(bool q, bool r) {return q;};
  template<size_t N> struct pow<N,0> {
    bool operator()(bool q, bool r, bool t) {return q;};
     enum {val=1};
};
struct Second {
     bool operator()(bool q, bool r) {return r;};
    bool operator()(bool q, bool r, bool t) {return r;};
  };
  struct Third {
     bool operator()(bool q, bool r, bool t) {return t;};
  };
  };


Dla przyspieszenia dodajemy dwie specjalizacje:
Następnie definiujemy klasę stałych logicznych:


  template<size_t M> struct pow<1,M>{
  class Constant {
     enum {val=1};
     bool _val;
};<br>
public
template<size_t M> struct pow<0,M>{
    Constant(bool q):_val(q) {};
     enum {val=0};
    bool operator()(bool q) {return _val;};
    bool operator()(bool q, bool r) {return _val;};
     bool operator()(bool q, bool r, bool s) {return _val;};
  };
  };


Powyższa specjalizacja spowoduje, że konkretyzacja <tt>Pow<0,0></tt> będzie niejednoznaczna. Możemy to tak zostawić, bo <math>0^0</math> jest nieokreślone. Jeśli jednak zdecydujemy się na jakąś wartość, np. zero, to należy dodać jeszcze jedną specjalizację:
i dwie globalne stałe:
 
namespace Logic {
Constant True(true);
Constant False(false);
}
 
Używamy przestrzeni nazw Logic aby zmniejszyć ryzyko konfliktu nazw.
 
Klasa <tt>And</tt> reprezentuje koniunkcję dwu wyrażeń logicznych:


  template<> struct pow<0,0>{
  template<typename L,typename R> class And {
     enum {val=0};
    L _lhs;
    R _rhs;
public:
    And(L l,R r):_lhs(l),_rhs(r) {};
    bool operator()(bool q) {return _lhs(q) && _rhs(q);}
     bool operator()(bool q, bool r) {return _lhs(q,r) && _rhs(q,r);}
    bool operator()(bool q, bool r, bool s) {return _lhs(q,r,s) && _rhs(q,r,s);}
  };
  };


Patrz plik [http://osilek.mimuw.edu.pl/images/b/b4/Logic.h logic.h].
Obiekty tej klasy są generowane przez operator:
 
template<typename L,typename R> And<L,R> operator&&(L l,R r)
    {return And<L,R>(l,r);}
 
Jeśli będziemy korzystać tylko z naszych stałych logicznych <tt>Logic::True</tt> i <tt>Logic::False</tt>, to niepotrzebne są dodatkowe przeciążenia operatora.
 
Pozostałe operatory implementujemy analogicznie. Całość kodu jest podana w pliku [http://osilek.mimuw.edu.pl/images/b/b4/Logic.h logic.h].
</div></div>
</div></div>



Wersja z 13:14, 21 wrz 2006

Ćwiczenie 1

Zaimplementuj szablony funkcji table1, table2 i table3, generujące tabele prawdy dla jednej, dwu lub trzech zmiennych logicznych. Argumentem tych funkcji ma być funkcja przyjmująca, w zależności od funkcji, od 1 do 3 argumentów typu bool, np.:

 bool And(bool q,bool r) {return q && r;}
 table2(And2) ;

powinno wygenerować :

--------------
| 0 | 0 || 0 |    
| 0 | 1 || 0 |    
| 1 | 0 || 0 |    
| 1 | 1 || 1 |    
--------------

Podobnie dla table1 i table3.

Rozwiązanie

Ćwiczenie 2

{{{3}}}
Rozwiązanie

Ćwiczenie 3

Zaimplementuj szablon funkcji, który będzie przyjmował jako jeden z parametrów szablonu ilość zmiennych logicznych i będzie łączył działanie funkcji table1, table2 i table3. Np.:

table<2>(And);

powinno być równoważne wywołaniu:

table2(And);
Podpowiedź
Rozwiązanie