Zaawansowane CPP/Ćwiczenia 12: Używanie funktorów: Różnice pomiędzy wersjami
Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 31: | Linia 31: | ||
op(*first1,*first2);<br> | op(*first1,*first2);<br> | ||
return op; | return op; | ||
} | } | ||
Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/0/08/For_each.h for_each.h]. | Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/0/08/For_each.h for_each.h]. | ||
Linia 60: | Linia 60: | ||
public: | public: | ||
adapt_t(Function f,Result val):_f(f),_val(val) {}; | adapt_t(Function f,Result val):_f(f),_val(val) {}; | ||
typedef Result result_type; | typedef Result result_type;<br> | ||
result_type operator()() {_f();return result_type(_val);}; | result_type operator()() {_f();return result_type(_val);}; | ||
result_type operator()(arg1_type a1) {_f(a1);return result_type(_val);}; | result_type operator()(arg1_type a1) {_f(a1);return result_type(_val);}; | ||
result_type operator()(arg1_type a1,arg2_type a2) {_f(a1,a2);return | result_type operator()(arg1_type a1,arg2_type a2) {_f(a1,a2);return | ||
result_type(_val);}; | result_type(_val);}; | ||
}; | }; | ||
Do tego dochodzi jeszcze specjalizacja dla {Result <nowiki> =</nowiki> void} i funkcje: | Do tego dochodzi jeszcze specjalizacja dla {Result <nowiki> =</nowiki> void} i funkcje: | ||
template<typename F> adapt_t<F,void> | template<typename R,typename F> adapt_t<F,R> | ||
adapt(F f) {return adapt_t<F,void>(f);} | adapt(F f,R val) {return adapt_t<F,R>(f,val);} | ||
template<typename F> adapt_t<F,void> | |||
Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/ | adapt(F f) {return adapt_t<F,void>(f);} | ||
Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/4/45/Dev_null.h dev_null.h]. | |||
</div></div> | </div></div> | ||
Linia 84: | Linia 81: | ||
Napisz iterator, który nic nie robi, ignorując przypisywane do niego elementy. | Napisz iterator, który nic nie robi, ignorując przypisywane do niego elementy. | ||
}} | }} | ||
<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"> | |||
Korzystamy z prostej klasy proxy: | Korzystamy z prostej klasy proxy: | ||
Linia 104: | Linia 90: | ||
której operator przypisania "połyka" swój argument. | której operator przypisania "połyka" swój argument. | ||
Kod znajduje się w pliku | Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/4/45/Dev_null.h dev_null.h]. | ||
</div></div> | |||
{{cwiczenie|4|| | |||
Zaimplementuj opisany w wykładzie iterator, który działa podaną funkcją na | |||
przypisywane obiekty. | |||
}} | |||
<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"> | |||
Iterator | Iterator | ||
template<typename F,typename T> | template<typename F,typename T> | ||
class exec_iterator_t: public std::iterator<std::output_iterator_tag,T> | class exec_iterator_t: public std::iterator<std::output_iterator_tag,T> | ||
{ | { | ||
F _fun; | |||
oparty jest o zagnieżdżoną klasę proxy: | oparty jest o zagnieżdżoną klasę proxy: | ||
struct do_it { | struct do_it { | ||
exec_iterator_t *_parent; | exec_iterator_t *_parent; | ||
do_it(exec_iterator_t *parent):_parent(parent) {}; | do_it(exec_iterator_t *parent):_parent(parent) {}; | ||
void operator<nowiki> =</nowiki> (const T& x) { _parent->_fun(x);} | void operator<nowiki> =</nowiki> (const T& x) { _parent->_fun(x);} | ||
}; | };<br> | ||
do_it _proxy; | |||
której operator przypisania wywołuje podaną funkcje na wartości mu | |||
przekazanej. Operator <tt>*</tt> zwraca obiekt proxy, a operatory | |||
której operator | <tt>++</tt> nie robią nic: | ||
przekazanej. Operator | |||
public: | public: | ||
exec_iterator_t(F fun):_fun(fun),_proxy(this) {}; | |||
do_it &operator*(){return _proxy;}; | |||
exec_iterator_t &operator++() {return *this;} | |||
void operator++(int) {} | |||
}; | }; | ||
Do utworzenia iteratora używamy szablon funkcji | Do utworzenia iteratora używamy szablon funkcji | ||
template<typename T,typename F> | template<typename T,typename F> | ||
exec_iterator_t<F,T> exec_iterator(F f){ | exec_iterator_t<F,T> exec_iterator(F f){ | ||
return exec_iterator_t<F,T>(f); | return exec_iterator_t<F,T>(f); | ||
}; | }; | ||
korzystając z automatycznej dedukcji typów. Kod znajduje się w pliku | korzystając z automatycznej dedukcji typów. | ||
Kod znajduje się w pliku [http://osilek.mimuw.edu.pl/images/4/45/Dev_null.h dev_null.h]. | |||
</div></div> |
Wersja z 11:36, 25 wrz 2006
Ćwiczenie 1
Napisz algorytm for_each
który działałby na dwu zakresach.
template<typename InputIterator1, typename InputIterator2, typename BinaryFunction op> BinaryFunction for_each(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryFunction op);
Algorytm ma działać tak jak standardowy for_each
, tyle że funkcja
op
ma być stosowana do par elementów:
op(*first1,*first2); op(*(first1+1),*(first2+1); ...
Rozwiązanie
Ćwiczenie 2
Zaimplementuj opisany na wykładzie adapter, który opakowuje funkcję lub funktor, ignorując zwracaną przez nie wartość i zwracający zamiast niej jakąś wartość wybranego typu. Np.:
double f(int); adapt(f,7)(0);
wywołuje f(0) i zwraca 7.
double f(int); adapt(f)(0);
wywołuje f(0) i nie wraca żadnej wartości.
Rozwiązanie
Ćwiczenie 3
Napisz iterator, który nic nie robi, ignorując przypisywane do niego elementy.
Rozwiązanie
Ćwiczenie 4
Zaimplementuj opisany w wykładzie iterator, który działa podaną funkcją na przypisywane obiekty.
Rozwiązanie