Zaawansowane CPP/Ćwiczenia 12: Używanie funktorów: 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 23: Linia 23:
    
    
  template<typename InputIterator1,
  template<typename InputIterator1,
  typename InputIterator2,  
          typename InputIterator2,  
  typename BinaryFunction >
          typename BinaryFunction >
  BinaryFunction for_each(InputIterator1 first1,InputIterator1 last1,
  BinaryFunction for_each(InputIterator1 first1,InputIterator1 last1,
InputIterator2 first2,
                        InputIterator2 first2,
BinaryFunction op) {<br>
                        BinaryFunction op) {<br>
   for(;first1!<nowiki> =</nowiki>  last1;++first1,++first2)
   for(;first1!<nowiki> =</nowiki>  last1;++first1,++first2)
     op(*first1,*first2);<br>
     op(*first1,*first2);<br>

Wersja z 11:25, 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.

Ćwiczenie 3

Napisz iterator, który nic nie robi, ignorując przypisywane do niego elementy.

Ćwiczenie 4

Zaimplementuj opisany w wykładzie iterator, który działa podaną funkcją na przypisywane obiekty.




Rozwiązanie 2

template<typename Function , typename Result > class adapt_t: public functor_traits<Function>::f_type {

 typedef typename functor_traits<Function>::arg1_type arg1_type;
 typedef typename functor_traits<Function>::arg2_type arg2_type;
 Function _f;
 Result  _val;
public:
 adapt_t(Function f,Result val):_f(f),_val(val) {};
 typedef Result result_type;
 
 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,arg2_type a2) {_f(a1,a2);return result_type(_val);};
 

};

Do tego dochodzi jeszcze specjalizacja dla {Result = void} i funkcje:

template<typename R,typename F> adapt_t<F,R> adapt(F f,R val) {return adapt_t<F,R>(f,val);}

template<typename F> adapt_t<F,void> adapt(F f) {return adapt_t<F,void>(f);}

Kod znajduje się w pliku {mod14/exercises/dev_null.h}devnull.h

Rozwiażanie 3

Korzystamy z prostej klasy proxy:

 struct sink {
   void operator =   (const T&) {};
 };

której operator przypisania "połyka" swój argument. Kod znajduje się w pliku {mod14/exercises/dev_null.h}devnull.h

Rozwiązanie 4

Iterator

template<typename F,typename T> class exec_iterator_t: public std::iterator<std::output_iterator_tag,T> {

 F _fun;
 

oparty jest o zagnieżdżoną klasę proxy:

struct do_it {

   exec_iterator_t *_parent;
   do_it(exec_iterator_t *parent):_parent(parent) {};
   void operator =   (const T& x) { _parent->_fun(x);}
 };
 do_it _proxy;

której operator przypisanie wywołuje podaną funkcje na wartości mu przekazanej. Operator {*} zwraca obiekt proxy, a operatory {++} nie robią nic:

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

template<typename T,typename F> exec_iterator_t<F,T> exec_iterator(F f){ return exec_iterator_t<F,T>(f); };

korzystając z automatycznej dedukcji typów. Kod znajduje się w pliku {mod14/exercises/exec_iterator.h}execiterator.h