23 Ağustos 2019 Cuma

STL Kopyalama Algoritmaları

Giriş
STL algoritmalarını işlevlerine göre gruplamak anlamayı çok daha kolaylaştırıyor. Aşağıdaki algoritmalar sıralı dizileri yine sıralı olarak birleştirmeyi gösteriyor.

copy
Açıklaması şöyle.
If the array contains type which is TriviallyCopyable, it calls memmove(), else it calls the assignment operator.
Açıklaması şöyle.
In practice, implementations of std::copy avoid multiple assignments and use bulk copy functions such as std::memmove if the value type is TriviallyCopyable
C++17 ile metodun içi şöyle
char* copy(char const* first, char const* last, char* d)
{
  memcpy(d, first, last - first);
  return d + (last - first);
}
C++20 ile metodun içi şöyle. Böylece bu metod constexpr zamanı da kullanılabiliyor.
constexpr char* copy(char const* first, char const* last, char* d)
{
  if (std::is_constant_evaluated()) {
    while (first != last) {
      *d++ = *first++;
    }
    return d;       
  } else {
    memcpy(d, first, last - first);
    return d + (last - first);
  }
}

copy_backward
Sırayı ters çevirerek kopyalar. a'nın başı b''nın sonuna gelir.
int a[10] = ...;
int b[10] = ...;
std::copy_backward( std::begin(a), std::end(a), std::end(b) );

copy_if
copy_if Linq'teki Where() filteri ile aynı işlevi görür.
Örnek
Şöyle yaparız.
std::vector<int> foo = {25,15,5,-5,-15};
std::vector<int> bar;

// copy only positive numbers:
auto it = std::copy_if (foo.begin(),foo.end(),
                        std::back_inserter(bar), [](int i){return i>=0;} );
Örnek
std::cin'den 10 tane int okumak için şöyle yaparız.
const int N = 10;
std::vector<int> v;
//optionally v.reserve(N);
std::copy_if(
  std::istream_iterator<int>(std::cin),
  std::istream_iterator<int>(), 
  std::back_inserter(v), 
  [count=N] (int)  mutable {
    return count && count--;
});
Örnek
copy_if input iterator ile outpute iterator tipinin aynı olmasın bekler. Elimizde struct içinde struct olsun.
struct Foo {};
struct FooBar{
  bool is_valid;
  Foo foo;
};
Şu kod derlenmez.
std::vector<Foo> get_valid_foos_modern(const std::vector<FooBar>& foobars){
  std::vector<Foo> valid_foos;
  std::copy_if(foobars.begin(), foobars.end(), std::back_inserter(valid_foos),
    [](const auto& foobar){
      return foobar.is_valid;
    });
  //?? std::copy requires input and output types to match
  return valid_foos;
}
copy_n
Metodun imzası şöyle. count kaç tane elemanı kopylamak istediğimizi belirtir. Bu sayı eksi olabilir.
template<class InputIt, class Size, class OutputIt>
OutputIt copy_n(InputIt first, Size count, OutputIt result);
Örnek
Elimizde şöyle bir kod olsun.
std::vector<int> source = { 1, 2, 3, 4, 5, 6, 7,};
Şöyle yaparız.
using std::begin;

std::copy_n(begin(source), 7, std::back_inserter(result));

Hiç yorum yok:

Yorum Gönder