Po Yen Chen @poyenc
© Po Yen Chen 2020
Background image ©
pair of iterators
© Po Yen Chen 2020
Background image ©
© Po Yen Chen 2020
Background image ©
InputIterator vs OutputIterator
InputIterator vs ForwardIterator
template <typename Iterator> requires std::output_iterator<Iterator, int>
void assign_zero(Iterator it) {
*it;
*it = 0;
}
template <typename Iterator> requires std::forward_iterator<Iterator>
void check_multi_pass(Iterator it) {
decltype(auto) before = *it;
std::next(it);
decltype(auto) after = *it;
assert(std::addressof(before) == std::addressof(after));
}
© Po Yen Chen 2020
Background image ©
const auto pi = [] {
std::vector<int> range;
return begin(range);
}();
// WARNING: its danger to use *pi from now
const auto pc = [] {
auto range = "hello"sv;
return begin(range);
}();
// ok to use *pc anywhere
© Po Yen Chen 2020
Background image ©
© Po Yen Chen 2020
Background image ©
std::vector<int> ints(10);
std::iota(begin(ints), end(ints), 1);
// create range of descending integers
assert(std::is_sorted(std::make_reverse_iterator(end(ints)),
std::make_reverse_iterator(begin(ints)),
std::greater<>()));
std::istringstream stream("96 27");
// create range of arbitrary integers
assert(std::accumulate(std::istream_iterator<int>(stream),
std::istream_iterator<int>(), 0) == 123);
There are no range-based libraries until C++20
© Po Yen Chen 2020
Background image ©
std::vector<unsigned> scores;
// fill score values here
decltype(scores) squared;
std::transform(
begin(scores), end(scores), std::back_inserter(squared),
[](auto score) { return std::sqrt(score); }
);
decltype(scores) enlarged;
std::transform(
begin(squared), end(squared), std::back_inserter(enlarged),
[](auto score) { return score * 10; }
);
std::cout << std::count_if(begin(enlarged), end(enlarged),
[](auto score) { return 60 <= score; })
<< std::endl;
© Po Yen Chen 2020
Background image ©
std::vector<unsigned> scores;
// fill score values here
std::cout << std::ranges::count_if(
scores
| ranges::view::transform([](auto score) { return std::sqrt(score); })
| ranges::view::transform([](auto score) { return score * 10; })
, [](auto score) { return 60 <= score; }
) << std::endl;
© Po Yen Chen 2020
Background image ©
More are coming in C++23
© Po Yen Chen 2020
Background image ©
The Customization Point
template <typename T>
void two_step_swap(T& a, T& b) {
using std::swap; // overload functions in namespace std are also candidates
swap(a, b); // customization point, may find match through ADL
}
namespace ns {
struct Foo {};
void swap(Foo&, Foo&) { // customized function
puts("customized swap");
}
}
ns::Foo a, b;
::two_step_swap(a, b); // ok to use qualified name here
© Po Yen Chen 2020
Background image ©
The Customization Point Object
const std::vector values{1.1, 2.2, 3.3};
std::ranges::transform(values, ranges::ostream_iterator<>(std::cout, " "),
std::floor);
// ^^^^^^^^^^ error: unresolved overloaded function type
modified version
inline constexpr struct {
template <typename T>
auto operator()(T value) const {
using std::floor;
return floor(value); // may invoke a customized function for T
}
} two_step_floor;
std::ranges::transform(values, ranges::ostream_iterator<>(std::cout, " "),
two_step_floor);
© Po Yen Chen 2020
Background image ©
#include <iostream>
#include <ranges>
#include <range/v3/iterator/stream_iterators.hpp>
#include <range/v3/view/cycle.hpp>
#include <range/v3/view/indices.hpp>
#include <range/v3/view/take.hpp>
int main() {
std::ranges::copy(ranges::view::indices(5) // ring-buffer size = 5
| ranges::view::cycle
| ranges::view::take(10), // desired sequence length = 10
ranges::ostream_iterator<>(std::cout, " "));
}
Let's dive into the source : cycle.hpp
© Po Yen Chen 2020
Background image ©
© Po Yen Chen 2020
Background image ©
© Po Yen Chen 2020
Background image ©