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 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 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>
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/0/08/For_each.h for_each.h].
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.  
}}
}}
{{cwiczenie|4||
Zaimplementuj opisany w wykładzie iterator, który działa podaną funkcją na
przypisywane obiekty.
}}
'''Rozwiażanie 3 '''


<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].
{mod14/exercises/dev_null.h}<tt>devnull.h</tt>
</div></div>


'''Rozwiązanie 4 '''
{{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;
  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;


  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 przypisanie wywołuje podaną funkcje na wartości mu
<tt>++</tt> nie robią nic:
przekazanej. Operator {*} zwraca obiekt proxy, a operatory  
{++} nie robią nic:
    
    
public:
public:
  exec_iterator_t(F fun):_fun(fun),_proxy(this) {};
  exec_iterator_t(F fun):_fun(fun),_proxy(this) {};
  do_it &operator*(){return _proxy;};
  do_it &operator*(){return _proxy;};
  exec_iterator_t &operator++() {return *this;}
  exec_iterator_t &operator++() {return *this;}
  void operator++(int) {}
  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.
{mod14/exercises/exec_iterator.h}<tt>execiterator.h</tt>
 
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