5 Mart 2018 Pazartesi

STL Applying Algoritmaları

Giriş
STL algoritmalarını işlevlerine göre gruplamak anlamayı çok daha kolaylaştırıyor.

for_each
Sadece algoritmayı göstermek için metodun içi şöyle düşünülebilir. Aslında return tipi void değil!
template <typename InputIterator, typename Functor>
void for_each(InputIterator first, InputIterator last, Functor f)
{
    while (first != last) f(*first++);
}
Gerçek metodun içi ve imzası şöyle.
template<typename _InputIterator, typename _Function>
_Function
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
{
  for (; __first != __last; ++__first)
    __f(*__first);
  return _GLIBCXX_MOVE(__f);
}
GCC'nin koduna karışmadan çok daha okunaklı bir gerçekleştirim şöyle.
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f)
{
  for ( ; first!=last; ++first ) f(*first);
  return f;
}
Verilen functor'ın kopyasını alır ve sonuç olarak döndürür. Sonuç olarak functor nesnesi döndürdüğü için functor içinde state tutabilir.

Paralel for_each
Şöyle yaparız.
std::for_each(std::execution::par_unseq, std::begin(indices), std::end(indices),
  [&](std::size_t const i) { ... });
Functor State Tutabilir
Functor state tutabilir ancak functor'ın döndürdüğü değer kullanılmaz. Açıklaması şöyle.
If f returns a result, the result is ignored.
Örnek
Şu kod functor state tutmadığı için çalışmaz.
vector<string> v;

if(not for_each(v.begin(), v.end(), [](const string& str) -> bool{
  ...;
  })
);
Örnek
State tutan şöyle bir functor kodum olsun.
class MyFunctor
{
   Y val;
   public:
     MyFunctor() : val() {}

     void operator()( X const& x )
     {
        // do something to modify val based on x
     }

     Y getValue() const { return val; }   
};
Bu functor'ı for_each ile kullanarak val değerini güncellerim ve nihai sonucu şöyle alırım.
Y y = for_each( coll.begin(), coll.end(), MyFunctor() ).getValue();
Örnek
Daha kullanışlı bir örnek şöyle. Elimizde 0-9 arası değerler içeren bir vector olsun.
std::vector<int> vec = {1,2,3,4,5,6,7,8,9};
Bu değerli toplayan bir sınıf yazalım.
template <class T>
class Sum {
private:
    T val;
public:
    Sum (T i = 0) : val(i) {
    }

    void operator()(T x) { 
        val += x; 
    }

    T result() const { 
        return val; 
    }
};
for_each sonuç döndüğü için toplam işleminin sonucunu şöyle alabiliriz.
Sum<int> s1 = std::for_each(vec.begin(), vec.end(), s);
Bu durumda 0'dan 9'a kadar olan sayıların toplamını alırız.

Yapılmaması Gerekekenler
for_each içinde silme yapılmamalıdır.
std::for_each(set.begin(), set.end(), 
    [&map](const std::string & s) { map.erase(s); });




Hiç yorum yok:

Yorum Gönder