Zaawansowane CPP/Ćwiczenia 11: Funktory: Różnice pomiędzy wersjami
Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Nie podano opisu zmian |
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 | 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 | 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 | 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/ | 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 .
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