ranges etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
ranges etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

26 Mayıs 2021 Çarşamba

std::views::filter metodu

Giriş
Açıklaması şöyle
In order to provide the amortized constant time complexity required by range, filter_view::begin caches the result in *this. This modifies the internal state of *this and thus cannot be done in a const member function.
Örnek
Elimizde şöyle bir kod olsun. const v olan kod derlenmez.
auto fn_is_l = [](auto const c) { return c == 'l'; };

{
  auto v = "hello"sv | std::views::filter(fn_is_l);
  std::cout << *v.begin() << std::endl; // ok
}

{
  auto const v = "hello"sv | std::views::filter(fn_is_l);
  std::cout << *v.begin() << std::endl; // error
}
Örnek
Şöyle yaparız.
#include <vector>
#include <ranges>
#include <iostream>

int main()
{
  std::vector<int> ints{0,1,2,3,4,5};
  auto even = [](int i){ return 0 == i % 2; };
  auto square = [](int i) { return i * i; };

  for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
    std::cout << i << ' ';
  }
}

$ g++-10 -Wall -Wextra -std=c++20 ranges.cpp 
$ ./a.out 
0 4 16

15 Şubat 2021 Pazartesi

views Kütüphanesi

Giriş
commons
std::views::common metodu yazısına taşıdım

std::views::filter metodu
std::views::filter metodu yazısına taşıdım

std::views::reverse
Örnek
Şöyle yaparız
#include <vector>
#include <ranges>

int main() {
  auto values = std::vector{1,2,3,4,5,6,7,8,9,10};
  auto even = [](const auto value) {
    return value % 2 == 0;
  };
  auto square = [](const auto value) {
    return value * value;
  };

  auto results1 = values
      | std::views::filter(even)
      | std::views::reverse
      | std::views::take(4)
      | std::views::reverse;

  auto results2 = values
      | std::views::transform(square)
      | std::views::reverse
      | std::views::take(4)
      | std::views::reverse;
  ...   
}
std::views::split metodu
std::views::split metodu yazısına taşıdım

24 Aralık 2020 Perşembe

ranges Views

Giriş
Açıklaması şöyle
A View is something that you apply on a range and performs some operation. A view does not own data and it's time to copy, move, assignment is constant.
Çoğu view için alternatif bir isim de var. Açıklaması şöyle
In general, you can use a view such as std::views::transform with the alternative name std::transform_view.
Alternatif isimler parametre olarak bir container/view alıyorlar. view olanlar ise "pipe" işareti ile kullanılıyorlar.

Örnek
Şöyle yaparız İlk kullanımda pipe işareti görülebilir. İkinci kullanımda ise parametre olarak pi container değişkeni geçiliyor.
auto print = [](char x) { std::cout << x; };
int main() { constexpr char pi[] { '3', '.', '1', '4', '1', '5', '9', '2', '6', '5' }; std::ranges::for_each(pi | std::ranges::views::take(8), print); std::cout << '\n'; std::ranges::for_each(std::ranges::take_view{pi, 8}, print); std::cout << '\n'; }
Çıktı olarak şunu alırız
3.141592
3.141592
Örnek
Şöyle yaparız. Burada alternatif isimler kullanıldığı için parametre olarak bir container/view geçiliyor.
const std::string s{"cosmos"};
 
const std::ranges::take_view tv{s, 3};
const std::ranges::ref_view rv{tv};
 
std::cout
  << std::boolalpha
  << "call empty() : " << rv.empty() << '\n'
  << "call size()  : " << rv.size() << '\n'
  << "call begin() : " << *rv.begin() << '\n'
  << "call end()   : " << *(rv.end()-1) << '\n'
  << "call data()  : " << rv.data() << '\n'
  << "call base()  : " << rv.base().size() << '\n' // ~> tv.size()
  << "range-for    : ";
 
for (const auto c: rv) { 
  std::cout << c; 
}
std::cout << '\n';
Çıktı olarak şunu alırız
call empty() : false
call size()  : 3
call begin() : c
call end()   : s
call data()  : cosmos
call base()  : 3
range-for    : cos

std::ranges::views::all - takes all elements
Alternatif : std::ranges::all_view
Örnek ver

std::ranges::views::chunk - C++23 ile geliyor
Örnek
Vector'deki yan yana elemanları pair haline getirmek için şöyle yaparız. 
#include <iostream>
#include <ranges>
#include <vector>

int main()
{
  std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
  auto chunk_to_pair = [](auto chunk)
  {
    return std::pair(*chunk.begin(), *std::next(chunk.begin()));
  };
  for (auto [first, second] : values | std::ranges::views::chunk(2)
    | std::ranges::views::transform(chunk_to_pair))
  {
    std::cout << first << second << std::endl;
  }
}
Aynı şeyi std::ranges::views::stride ile şöyle yaparız
#include <iostream>
#include <ranges>
#include <vector>

int main()
{
  std::vector<int> values = {1,2,3,4,5,6,7,8,9,10};
  auto odds = values | std::ranges::views::drop(0) | std::ranges::views::stride(2);
  auto evens = values | std::ranges::views::drop(1) | std::ranges::views::stride(2);
  for (auto [first, second] : std::ranges::views::zip(odds, evens))
  {
    std::cout << first << second << std::endl;
  }
}
std::ranges::ref_view - takes all elements of another view
Alternatif : Yok
Örnek ver

std::ranges::istream_view - applies operator>> on the view
Alternatif : std::ranges::basic_istream_view
Örnek ver

std::ranges::views::common - converts a view into a std::common_range
Alternatif : std::ranges::common_view
Örnek ver

std::ranges::views::drop - skips the first N elements of another view
Alternatif : std::ranges::drop_view
Örnek ver

std::ranges::views::drop_while - skips the initial elements of another view until the predicate returns false
Alternatif :std::ranges::drop_while_view
Örnek ver

std::ranges::views::elements - creates a view on the N-th element of tuples
Alternatif : std::ranges::elements_view
Örnek ver

std::ranges::views::filter - takes the elements which satisfies the predicate
Alternatif : std::ranges::filter_view
Örnek ver

std::ranges::views::join - joins a view of ranges
Alternatif : std::ranges::join_view
Örnek ver

std::ranges::views::keys - creates a view on the first element of a pair-like values
Alternatif : std::ranges::keys_view
Örnek ver

std::ranges::views::reverse - iterates in reverse order
Alternatif : std::reverse_view
Örnek ver

std::ranges::views::split - splits a view by using a delimiter
Alternatif : std::ranges::split_view
Örnek ver

std::ranges::views::take - takes the first N elements of another view
Alternatif : std::ranges::take_view
Örnek ver

std::ranges::views::take_while - takes the elements of another view as long as the predicate returns true
Alternatif : std::ranges::take_while_view
Örnek ver

std::ranges::views::transform - transforms each element
Alternatif : std::ranges::transform_view
Örnek ver

std::ranges::views::values - creates a view on the second elements of a pair-like values
Alternatif : std::ranges::values_view
Örnek ver

ranges Generators

std::ranges::empty_view
Örnek ver

std::ranges::iota_view
Örnek
Şöyle yaparız
std::vector<int> const v = ...;
std::ranges::iota_view<std::size_t, std::size_t> const indices(0u, u.size());
Daha sonra kullanmak için şöyle yaparız
std::begin(indices), std::end(indices)

std::ranges::single_view
Örnek ver

28 Ağustos 2020 Cuma

ranges Kütüphanesi

Giriş
C++20 ile geliyor. Temel amacı lazy evaluation

Neden Aynı Algoritma İsimleri
STL içinde iterator alan algoritma isimleri aynı zamanda ranges içinde de var. Sebebi STL algoritmalarını iterator kullanması, ancak ranges iterator dönmüyor, sentinel denen bir nesne dönüyor. Dolayısıyla şu kod derlenmez
#include <ranges>
#include <numeric>
#include <iostream>

int main() {
  auto rng = std::ranges::istream_view<int>(std::cin);
  std::cout << std::accumulate(std::ranges::begin(rng), std::ranges::end(rng), 0);
}
Açıklaması şöyle
The problem is that the end of a C++ range is not, in the general case, an iterator, but rather, a sentinel. A sentinel can have a different type than an iterator and admit fewer operations - as, generally speaking, you mostly need to compare against it to know you've reached the end of the range, and may not be allowed to just work with it like any iterator.
Açıklaması şöyle
While a lot of algorithms added corresponding overloads into std::ranges, the ones in <numeric> were left out. There is a std::accumulate but there is no std::ranges::accumulate
Dolayısıyla C++ içinde birbirine uyumsuz stream, iterator nesneleri yanında bir range nesnesi geldi.

Generators
ranges Generators yazısına taşıdım.

std::ranges::contiguous_range metodu
Parametrenin std::ranges::random_access_range olması gerekir. Tanımı şöyle
template<class T>
concept contiguous_range =
  ranges::random_access_range<T> &&
  std::contiguous_iterator<ranges::iterator_t<T>> &&
  requires(T& t) {
    { ranges::data(t) } ->
      std::same_as<std::add_pointer_t<ranges::range_reference_t<T>>>;
  };
Örnek
Şöyle yaparız
struct ntbs_sentinel {
  bool operator==(char const* p) const {
    return *p == '\0';
  }
};

struct ntbs {
  char const* p;
  char const* begin() const { return p; }
  ntbs_sentinel end() const { return {}; }
};

static_assert(std::ranges::contiguous_range<ntbs>);
static_assert(!std::ranges::sized_range<ntbs>);
std::ranges::fill metodu
Şöyle yaparız.
#include <algorithm>
#include <cassert>
#include <span>

namespace ranges = std::ranges;

int main()
{
  int arr[] {1, 7, 3, 2, 0, 5, 0, 8};

  const std::span spn{arr};
  ranges::fill(spn, 173);               // this compiles

  assert(ranges::count(arr, 173) == 8); // passes
}
std::ranges::find metodu
İki tane overload edilmiş hali var. Bunlar şöyle
namespace ranges {
  template<input_­iterator I, sentinel_­for<I> S, class T, class Proj = identity>
    requires indirect_­binary_­predicate<ranges::equal_to, projected<I, Proj>, const T*>
    constexpr I find(I first, S last, const T& value, Proj proj = {});

  template<input_­range R, class T, class Proj = identity>
    requires indirect_­binary_­predicate<ranges::equal_to,
                                       projected<iterator_t<R>, Proj>, const T*>
    constexpr borrowed_iterator_t<R>
      find(R&& r, const T& value, Proj proj = {});
}
std::ranges::istream_view metodu
Açıklaması şöyle
There is a utility to wrap a C++20 range into a C++17-compatible one: views::common
istream_view's iterators aren't copyable, and in C++17 all iterators must be. So there isn't really a way to provide C++17-compatible iterators based on istream_view.
Örnek
Şöyle yaparız
auto rng = std::ranges::istream_view<int>(ints) | std::views::common;
std::cout << std::accumulate(rng.begin(), rng.end(), 0);
std::ranges::range metodu
Örnek
Şöyle yaparız.
template<typename T>
concept nested_range = std::ranges::range<T> && 
std::ranges::range<std::ranges::range_value_t<T>>
Açıklaması şöyle
If you want to ask if a type is a range which itself contains a range, that's simply applying the std::range type twice
std::ranges::swap metodu
Örnek
Şöyle yaparız
#include <concepts>
#include <iostream>

struct dummy {
  friend void swap(dummy& a, dummy& b) {
    std::cout << "ADL" << std::endl;
  }
};

int main()
{
  int a{};
  int b{};
  dummy c{};
  dummy d{};
  std::ranges::swap(a, b);
  std::ranges::swap(c, d); // Ok. Prints "ADL" on console.
}