Zaawansowane CPP/Ćwiczenia 11: Funktory: 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 112: Linia 112:


<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">
Zaczynamy od implemenatcji adaptera {call}. W tym celu defiuniujemy
Zaczynamy od implemenatcji adaptera <tt>call</tt>. W tym celu definiujemy
szablon:
szablon:
   
 
template<typename F,typename A1,typename A2> struct call_t2: public  
  template<typename F,typename A1,typename A2> struct call_t2: public  
std::binary_function<A1,
std::binary_function<A1,
    A2,
    A2,
    typename functor_traits<F>::result_type> {
    typename functor_traits<F>::result_type> {
   typedef typename functor_traits<F>::result_type result_type;
   typedef typename functor_traits<F>::result_type result_type;
   typedef typename functor_traits<F>::arg1_type arg1_type;
   typedef typename functor_traits<F>::arg1_type arg1_type;
   typedef typename functor_traits<F>::arg2_type arg2_type;
   typedef typename functor_traits<F>::arg2_type arg2_type;<br>
 
   F _f;<br>
   F _f;
  public:
  public:
  call_t2(F f):_f(f) {};
  call_t2(F f):_f(f) {};
 
który wyposażamy w trzy funkcje:
który wyposażamy w trzy funkcje:
   
   
   result_type call(A1 a1,A2 a2,  
   result_type call(A1 a1,A2 a2,  
Linia 142: Linia 140:
     return _f(a1,a2);
     return _f(a1,a2);
   };
   };
 
Ostatni argument służy do tylko do przeciążenia funkcji wykorzystanego w operatorze nawiasów:
Ostatni argument służy do tylko do przeciążenia funkcji wykorzystanego w operatorze nawiasów:
   
   
Linia 148: Linia 146:
     return call(a1,a2,typename functor_traits<F>::f_type());
     return call(a1,a2,typename functor_traits<F>::f_type());
   };  
   };  
 
Jak zwykle dodajemy funkcję:
Jak zwykle dodajemy funkcję:
   
   
template<typename A1,typename A2,typename F> call_t2<F,A1,A2> call(F f) {
template<typename A1,typename A2,typename F> call_t2<F,A1,A2> call(F f) {
return call_t2<F,A1,A2>(f);}
return call_t2<F,A1,A2>(f);}
 
Podobnie definiujemy jednoargumentową wersję tego szablonu. {call_t1} i przeciążoną funkcję:
Podobnie definiujemy jednoargumentową wersję tego szablonu. {call_t1} i przeciążoną funkcję:
 
template<typename A1,typename F> call_t1<F,A1> call(F f) {
template<typename A1,typename F> call_t1<F,A1> call(F f) {
return call_t1<F,A1>(f);}
return call_t1<F,A1>(f);}
 
Całość kodu znajduje się w pliku {mod10/exercises/call.h}<tt>call.h</tt>.
Całość kodu znajduje się w pliku [http://osilek.mimuw.edu.pl/images/5/5b/Mixed_macro.h mixed_macro.h].


Implementując adapter {macro} musimy umieć poznać która z dwu przekazanych  
Implementując adapter {macro} musimy umieć poznać która z dwu przekazanych  
Linia 172: Linia 170:
     typename functor_traits<F2>::f_type>::Result  m_type;
     typename functor_traits<F2>::f_type>::Result  m_type;
};
};
 
 
Korzystając z {macro_type} i {call} możemy zaimplementować szablon:
Korzystając z {macro_type} i {call} możemy zaimplementować szablon:
 
template<typename F1,typename F2>  class macro_t :
template<typename F1,typename F2>  class macro_t :
public macro_type<F1,F2>::m_type {
public macro_type<F1,F2>::m_type {
  public:
  public:
   typedef void result_type ;
   typedef void result_type ;
 
Proszę zwrócić uwagę, że dziedzicząc z { macro_type<F1,F2>::m_type}
Proszę zwrócić uwagę, że dziedzicząc z { macro_type<F1,F2>::m_type}
defiuniujemy poprawne typy argumentów fuktora, ale niekoniecznie dobry
defiuniujemy poprawne typy argumentów fuktora, ale niekoniecznie dobry
typ wartości zwracanej. Dlatego redefinujemy go potem na {void}.
typ wartości zwracanej. Dlatego redefinujemy go potem na {void}.
Całość kodu znajduje się w pliku [http://osilek.mimuw.edu.pl/images/a/a3/Macro.h macro.h].
Całość kodu znajduje się w pliku [http://osilek.mimuw.edu.pl/images/5/5b/Mixed_macro.h mixed_macro.h].
</div></div>
</div></div>

Wersja z 10:55, 25 wrz 2006

Ćwiczenie 1

Zaimplementuj adapter compose_f_gx_hy realizujący złożenie dwuargumentowe f(g(x),h(y)).

Rozwiązanie

Ćwiczenie 2

Korzystając z klasy functor_traits zaimplementuj adpter bind1st, który bedzie działał zarówno dla funktorów jedno-, jak i dwuargumentowych.

Rozwiązanie

Ćwiczenie 3

Zaimplementuj funktor implementujący, składanie funkcji poprzez wykonywanie ich po kolei np.:

macro(f1,f2)(x)

powinno wykonać

f1(x);f2(x);

Wartości zwracane przez te funkcje są ignorowane. Funkcja macro powinna zwracać funktor odpowiedniego typu (posiadający odpowiednie typy stowarzyszone) tak, aby możliwe było dalsze składanie np.:

macro(macro(f1,f2),f3)(x)

powinno wywołać:

f1(x);f2(x);f3(x);
Rozwiązanie

Ćwiczenie 4

Zmodyfikuj powyższy szablon tak aby można było mieszać funkcje o różnej liczbie agrgumentów np.:

int f();
void g(double);
void h(double,int);
macro(f,g)(x);

powinno wywołać

f();g(x)}

a

macro(g,h)(3.14,0);

powinno wywołać

g(3.14);h(3.14,0)
Podpowiedź
Rozwiązanie