Giriş
C++20 ile geliyor. Temel amacı lazy evaluation
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
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.
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 = {});
}
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.
}