Zaawansowane CPP/Ćwiczenia 12: Używanie funktorów: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
 
(Nie pokazano 12 wersji utworzonych przez 2 użytkowników)
Linia 9: Linia 9:
 
                         InputIterator1 last1,
 
                         InputIterator1 last1,
 
                         InputIterator2 first2,
 
                         InputIterator2 first2,
                         BinaryFunction op);
+
                         BinaryFunction op);</nowiki>
</nowiki>
 
  
 
Algorytm ma działać tak jak standardowy <code><nowiki>for_each</nowiki></code>, tyle że funkcja
 
Algorytm ma działać tak jak standardowy <code><nowiki>for_each</nowiki></code>, tyle że funkcja
Linia 19: Linia 18:
 
...</nowiki>
 
...</nowiki>
 
}}
 
}}
 +
 +
<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">
 +
To rozwiązanie nie wymaga chyba komentarza.
 +
 
 +
template<typename InputIterator1,
 +
          typename InputIterator2,
 +
          typename BinaryFunction >
 +
BinaryFunction for_each(InputIterator1 first1,InputIterator1 last1,
 +
                        InputIterator2 first2,
 +
                        BinaryFunction op) {<br>
 +
  for(;first1!<nowiki> =</nowiki>  last1;++first1,++first2)
 +
    op(*first1,*first2);<br>
 +
  return op;
 +
}
 +
 +
Kod znajduje się w pliku [[media:For_each.h | for_each.h]].
 +
</div></div>
 +
 
{{cwiczenie|2||
 
{{cwiczenie|2||
  
Zaimplementuj opisany na wykładzie adapter który
+
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.:
opakowywuje funkcję lub funktor, ignorując zwracaną przez nie wartość
+
i zwracający zamiast jakąś wartość wybranego typu. Napisać wersje dla
+
double f(int);
funkcji jedno i dwu argumentowychDo niego napisz iterator, który
+
adapt(f,7)(0);
nic nie robi, ignorując przypisywane do niego elementy.  
+
 
 +
wywołuje <tt>f(0)</tt> i zwraca <tt>7</tt>.
 +
 
 +
double f(int);
 +
  adapt(f)(0);
 +
 
 +
wywołuje <tt>f(0)</tt> i nie zwraca żadnej wartości.
 
}}
 
}}
 +
 +
<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">
 +
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;<br>
 +
  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 <tt>Result <nowiki> =</nowiki>    void</tt> 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 [[media:Dev_null.h | dev_null.h]].
 +
</div></div>
 +
 
{{cwiczenie|3||  
 
{{cwiczenie|3||  
  
Zaimplementuj opisany w wykładzie iterator, który działa podaną funkcja na
+
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:
 +
 +
  struct sink {
 +
    void operator<nowiki> =</nowiki>  (const T&) {};
 +
  };
 +
 
 +
której operator przypisania "połyka" swój argument.
 +
Kod znajduje się w pliku [[media: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.
 
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
 +
 +
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<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
 +
<tt>++</tt> 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 [[media:Exec_iterator.h | exec_iterator.h]].
 +
</div></div>

Aktualna wersja na dzień 10:48, 2 paź 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 zwraca ż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