0% found this document useful (0 votes)
33 views29 pages

RANGES

RANGES_ bscs

Uploaded by

Hijab Ejaz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views29 pages

RANGES

RANGES_ bscs

Uploaded by

Hijab Ejaz
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

RANGES:

// rangesFilterTransform.cpp

#include <iostream>
#include <ranges>
#include <vector>

int main() {

std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

auto results = numbers | std::views::filter([](int n){ return n % 2 ==


0; })
| std::views::transform([](int n){ return n *
2; });

for (auto v: results) std::cout << v << " "; // 4 8 12

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::all_view, std::views::all // takes all elements

std::ref_view // takes all elements of


another view

std::filter_view, std::views::filter // takes the elements which


satisfies the predicate

std::transform_view, std::views::transform // transforms each element

std::take_view, std::views::take // takes the first N elements


of another view

std::take_while_view, std::views::take_while // takes the elements of


another view as long as the predicate returns true

std::drop_view, std::views::drop // skips the first N elements


of another view

std::drop_while_view, std::views::drop_while // skips the initial elements


of another view until the predicate returns false

std::join_view, std::views::join // joins a view of ranges


std::split_view, std::views::split // splits a view by using a
delimiter

std::common_view, std::views::common // converts a view into a


std::common_range

std::reverse_view, std::views::reverse // iterates in reverse order

std::basic_istream_view, std::istream_view // applies operator>> on the


view

std::elements_view, std::views::elements // creates a view on the N-th


element of tuples

std::keys_view, std::views::keys // creates a view on the


first element of a pair-like values

std::values_view, std::views::values // creates a view on the


second elements of a pair-like values
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
ALL THE FOLLOWING FUNCTIONS WORK WITHOUT THE RANGES::
Std::ranges::for_each
Parameters
first, last - iterator-sentinel pair denoting the range to apply the function to
r - the range of elements to apply the function to
f - the function to apply to the projected range
proj - projection to apply to the elements
Return value
{std::ranges::next(std::move(first), last), std::move(f)}

The following example uses a lambda expression to increment all of the elements of a vector
and then uses an overloaded operator() in a functor to compute their sum. Note that to compute
the sum, it is recommended to use the dedicated algorithm std::accumulate.

Run this code


#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

struct Sum
{
void operator()(int n) { sum += n; }
int sum {0};
};

int main()
{
std::vector<int> nums {3, 4, 2, 8, 15, 267};

auto print = [](const auto& n) { std::cout << ' ' << n; };

namespace ranges = std::ranges;


std::cout << "before:";
ranges::for_each(std::as_const(nums), print);
print('\n');

ranges::for_each(nums, [](int& n) { ++n; });

// calls Sum::operator() for each number


auto [i, s] = ranges::for_each(nums.begin(), nums.end(), Sum());
assert(i == nums.end());

std::cout << "after: ";


ranges::for_each(nums.cbegin(), nums.cend(), print);

std::cout << "\n" "sum: " << s.sum << '\n';

using pair = std::pair<int, std::string>;


std::vector<pair> pairs {{1,"one"}, {2,"two"}, {3,"tree"}};

std::cout << "project the pair::first: ";


ranges::for_each(pairs, print, [](const pair& p) { return p.first; });

std::cout << "\n" "project the pair::second:";


ranges::for_each(pairs, print, &pair::second);
print('\n');
}
Output:

before: 3 4 2 8 15 267
after: 4 5 3 9 16 268
sum: 305
project the pair::first: 1 2 3
project the pair::second: one two tree
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///

Std::ranges::all_of
Parameters
first, last - the range of the elements to examine
r - the range of the elements to examine
pred - predicate to apply to the projected elements
proj - projection to apply to the elements
Return value
1,2) true if std::invoke(pred, std::invoke(proj, *i)) != false for every iterator i in the range, false
otherwise. Returns true if the range is empty.

Example
Run this code
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

namespace ranges = std::ranges;

constexpr bool some_of(auto&& r, auto&& pred) // some but not all


{
return not (ranges::all_of(r, pred) or ranges::none_of(r, pred));
}

constexpr auto w = {1, 2, 3};


static_assert(!some_of(w, [](int x) { return x < 1; }));
static_assert( some_of(w, [](int x) { return x < 2; }));
static_assert(!some_of(w, [](int x) { return x < 4; }));

int main()
{
std::vector<int> v(10, 2);
std::partial_sum(v.cbegin(), v.cend(), v.begin());
std::cout << "Among the numbers: ";
ranges::copy(v, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';

if (ranges::all_of(v.cbegin(), v.cend(), [](int i) { return i % 2 == 0; }))


std::cout << "All numbers are even\n";

if (ranges::none_of(v, std::bind(std::modulus<int>(),
std::placeholders::_1, 2)))
std::cout << "None of them are odd\n";
auto DivisibleBy = [](int d)
{
return [d](int m) { return m % d == 0; };
};

if (ranges::any_of(v, DivisibleBy(7)))
std::cout << "At least one number is divisible by 7\n";
}

Output:
Among the numbers: 2 4 6 8 10 12 14 16 18 20
All numbers are even
None of them are odd
At least one number is divisible by 7

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::find, std::ranges::find_if, std::ranges::find_if_not
Parameters
first, last - the range of elements to examine
r - the range of the elements to examine
value - value to compare the elements to
pred - predicate to apply to the projected elements
proj - projection to apply to the elements
Return value
Iterator to the first element satisfying the condition or iterator equal to last if no such element is
found.

Example
Run this code
#include <algorithm>
#include <format>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

void projector_example()
{
struct folk_info
{
unsigned uid;
std::string name, position;
};

std::vector<folk_info> folks
{
{0, "Ana", "dev"},
{1, "Bob", "devops"},
{2, "Eve", "ops"}
};

const auto who{"Eve"};


if (auto it = std::ranges::find(folks, who, &folk_info::name); it !=
folks.end())
std::cout << std::format("Profile:\n"
" UID: {}\n"
" Name: {}\n"
" Position: {}\n\n",
it->uid, it->name, it->position);
}

int main()
{
namespace ranges = std::ranges;

projector_example();

const int n1 = 3;
const int n2 = 5;
const auto v = {4, 1, 3, 2};

if (ranges::find(v, n1) != v.end())


std::cout << "v contains: " << n1 << '\n';
else
std::cout << "v does not contain: " << n1 << '\n';

if (ranges::find(v.begin(), v.end(), n2) != v.end())


std::cout << "v contains: " << n2 << '\n';
else
std::cout << "v does not contain: " << n2 << '\n';

auto is_even = [](int x) { return x % 2 == 0; };

if (auto result = ranges::find_if(v.begin(), v.end(), is_even); result !=


v.end())
std::cout << "First even element in v: " << *result << '\n';
else
std::cout << "No even elements in v\n";

if (auto result = ranges::find_if_not(v, is_even); result != v.end())


std::cout << "First odd element in v: " << *result << '\n';
else
std::cout << "No odd elements in v\n";

auto divides_13 = [](int x) { return x % 13 == 0; };

if (auto result = ranges::find_if(v, divides_13); result != v.end())


std::cout << "First element divisible by 13 in v: " << *result << '\n';
else
std::cout << "No elements in v are divisible by 13\n";

if (auto result = ranges::find_if_not(v.begin(), v.end(), divides_13);


result != v.end())
std::cout << "First element indivisible by 13 in v: " << *result <<
'\n';
else
std::cout << "All elements in v are divisible by 13\n";
}

Output:
Profile:
UID: 2
Name: Eve
Position: ops

v contains: 3
v does not contain: 5
First even element in v: 4
First odd element in v: 1
No elements in v are divisible by 13
First element indivisible by 13 in v: 4

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::count, std::ranges::count_if
Parameters
first, last - the range of elements to examine
r - the range of the elements to examine
value - the value to search for
pred - predicate to apply to the projected elements
proj - projection to apply to the elements
Return value
Number of elements satisfying the condition.

Example
Run this code
#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
std::vector<int> v{1, 2, 3, 4, 4, 3, 7, 8, 9, 10};

namespace ranges = std::ranges;

// determine how many integers in a std::vector match a target value.


int target1 = 3;
int target2 = 5;
int num_items1 = ranges::count(v.begin(), v.end(), target1);
int num_items2 = ranges::count(v, target2);
std::cout << "number: " << target1 << " count: " << num_items1 << '\n';
std::cout << "number: " << target2 << " count: " << num_items2 << '\n';

// use a lambda expression to count elements divisible by 3.


int num_items3 = ranges::count_if(v.begin(), v.end(), [](int i){ return i %
3 == 0; });
std::cout << "number divisible by three: " << num_items3 << '\n';

// use a lambda expression to count elements divisible by 11.


int num_items11 = ranges::count_if(v, [](int i){ return i % 11 == 0; });
std::cout << "number divisible by eleven: " << num_items11 << '\n';
}

Output:
number: 3 count: 2
number: 5 count: 0
number divisible by three: 3
number divisible by eleven: 0

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::mismatch
Parameters
first1, last1 - an iterator-sentinel pair denoting the first range of the elements to
compare
r1 - the first range of the elements to compare
first2, last2 - an iterator-sentinel pair denoting the second range of the elements to
compare
r2 - the second range of the elements to compare
pred - predicate to apply to the projected elements
proj1 - projection to apply to the first range of elements
proj2 - projection to apply to the second range of elements
Return value
ranges::mismatch_result with iterators to the first two non-equal elements.

If no mismatches are found when the comparison reaches last1 or last2, whichever happens
first, the object holds the end iterator and the corresponding iterator from the other range.

Example
This program determines the longest substring that is simultaneously found at the very beginning and at the
very end of the given string, in reverse order (possibly overlapping).

Run this code


#include <algorithm>
#include <iostream>
#include <ranges>
#include <string_view>

[[nodiscard]]
constexpr std::string_view mirror_ends(const std::string_view in)
{
const auto end = std::ranges::mismatch(in, in | std::views::reverse).in1;
return {in.cbegin(), end};
}

int main()
{
std::cout << mirror_ends("abXYZba") << '\n'
<< mirror_ends("abca") << '\n'
<< mirror_ends("ABBA") << '\n'
<< mirror_ends("level") << '\n';

using namespace std::literals::string_view_literals;

static_assert("123"sv == mirror_ends("123!@#321"));
static_assert("radar"sv == mirror_ends("radar"));
}

Output:
ab
a
ABBA
level

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::equal
Parameters
first1, last1 - an iterator-sentinel pair denoting the first range of the elements to
compare
r1 - the first range of the elements to compare
first2, last2 - an iterator-sentinel pair denoting the second range of the elements to
compare
r2 - the second range of the elements to compare
pred - predicate to apply to the projected elements
proj1 - projection to apply to the first range of elements
proj2 - projection to apply to the second range of elements
Return value
If the length of the range [first1, last1) does not equal the length of the range [first2, last2),
returns false.

If the elements in the two ranges are equal after projection, returns true.
Otherwise returns false.
Example
The following code uses ranges::equal to test if a string is a palindrome.

Run this code


#include <algorithm>
#include <iomanip>
#include <iostream>
#include <ranges>
#include <string_view>

constexpr bool is_palindrome(const std::string_view s)


{
namespace views = std::views;
auto forward = s | views::take(s.size() / 2);
auto backward = s | views::reverse | views::take(s.size() / 2);
return std::ranges::equal(forward, backward);
}

void test(const std::string_view s)


{
std::cout << std::quoted(s) << " is "
<< (is_palindrome(s) ? "" : "not ")
<< "a palindrome\n";
}

int main()
{
test("radar");
test("hello");
static_assert(is_palindrome("ABBA") and not is_palindrome("AC/DC"));
}

Output:
"radar" is a palindrome
"hello" is not a palindrome

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::copy, std::ranges::copy_if
Parameters
first, last - the range of elements to copy
r - the range of elements to copy
result - the beginning of the destination range.
pred - predicate to apply to the projected elements
proj - projection to apply to the elements
Return value
A ranges::in_out_result containing an input iterator equal to last and an output iterator past the
last element copied.
Example
The following code uses ranges::copy to both copy the contents of one std::vector to another and to
display the resulting std::vector:

Run this code


#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main()
{
std::vector<int> source(10);
std::iota(source.begin(), source.end(), 0);

std::vector<int> destination;

std::ranges::copy(source.begin(), source.end(),
std::back_inserter(destination));
// or, alternatively,
// std::vector<int> destination(source.size());
// std::ranges::copy(source.begin(), source.end(), destination.begin());
// either way is equivalent to
// std::vector<int> destination = source;

std::cout << "destination contains: ";

std::ranges::copy(destination, std::ostream_iterator<int>(std::cout, " "));


std::cout << '\n';

std::cout << "odd numbers in destination are: ";

std::ranges::copy_if(destination, std::ostream_iterator<int>(std::cout, "


"),
[](int x) { return (x % 2) == 1; });
std::cout << '\n';
}

Output:
destination contains: 0 1 2 3 4 5 6 7 8 9
odd numbers in destination are: 1 3 5 7 9

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::transform
Parameters
first1, last1 - the first range of elements to transform
r, r1 - the first range of elements to transform
first2, last2 - the second range of elements to transform
r2 - the second range of elements to transform
result - the beginning of the destination range, may be equal to first1 or first2
op, binary_op - operation to apply to the projected element(s)
proj1 - projection to apply to the elements in the first range
proj2 - projection to apply to the elements in the second range
Return value
1,2) A unary_transform_result contains an input iterator equal to last and an output iterator to
the element past the last element transformed.

Example
The following code uses ranges::transform to convert a string in place to uppercase using the
std::toupper function and then transforms each char to its ordinal value. Then ranges::transform
with a projection is used to transform elements of std::vector<Foo> into chars to fill a std::string.

Run this code


#include <algorithm>
#include <cctype>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

int main()
{
std::string s{"hello"};
auto op = [](unsigned char c) -> unsigned char { return std::toupper(c); };

namespace ranges = std::ranges;

// uppercase the string in-place


ranges::transform(s.begin(), s.end(), s.begin(), op );

std::vector<std::size_t> ordinals;
// convert each char to size_t
ranges::transform(s, std::back_inserter(ordinals),
[](unsigned char c) -> std::size_t { return c; });

std::cout << s << ':';


for (auto ord : ordinals)
std::cout << ' ' << ord;

// double each ordinal


ranges::transform(ordinals, ordinals, ordinals.begin(), std::plus {});

std::cout << '\n';


for (auto ord : ordinals)
std::cout << ord << ' ';
std::cout << '\n';
struct Foo
{
char bar;
};
const std::vector<Foo> f = {{'h'},{'e'},{'l'},{'l'},{'o'}};
std::string result;
// project, then uppercase
ranges::transform(f, std::back_inserter(result), op, &Foo::bar);
std::cout << result << '\n';
}

Output:
HELLO: 72 69 76 76 79
144 138 152 152 158
HELLO

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::replace
Parameters
first, last - the range of elements to process
r - the range of elements to process
old_value - the value of elements to replace
new_value - the value to use as a replacement
pred - predicate to apply to the projected elements
proj - projection to apply to the elements
Return value
An iterator equal to last.

Example
Run this code
#include <algorithm>
#include <array>
#include <iostream>

int main()
{
auto print = [](const auto& v)
{
for (const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
};

std::array p {1, 6, 1, 6, 1, 6};


print(p);
std::ranges::replace(p, 6, 9);
print(p);

std::array q {1, 2, 3, 6, 7, 8, 4, 5};


print(q);
std::ranges::replace_if(q, [](int x) { return 5 < x; }, 5);
print(q);
}

Output:
1 6 1 6 1 6
1 9 1 9 1 9
1 2 3 6 7 8 4 5
1 2 3 5 5 5 4 5

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::replace_copy, std::replace_copy_if
Parameters
first, last - the range of elements to copy
d_first - the beginning of the destination range
old_value - the value of elements to replace
policy - the execution policy to use. See execution policy for details.
p - unary predicate which returns ​true if the element value should be replaced.
The expression p(v) must be convertible to bool for every argument v of type (possibly const)
VT, where VT is the value type of InputIt, regardless of value category, and must not modify v.
Thus, a parameter type of VT&is not allowed, nor is VT unless for VT a move is equivalent to a
copy(since C++11).​

new_value - the value to use as replacement


Type requirements
-InputIt must meet the requirements of LegacyInputIterator.
-OutputIt must meet the requirements of LegacyOutputIterator.
-ForwardIt1, ForwardIt2 must meet the requirements of LegacyForwardIterator.
Return value
Iterator to the element past the last element copied.

Example
The following copy-prints a vector, replacing all values over 5 with 99 on the fly.

Run this code


#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
std::vector<int> v{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
std::replace_copy_if(v.begin(), v.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int n){ return n > 5; }, 99);
std::cout << '\n';
}

Output:
5 99 4 2 99 99 1 99 0 3

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::fill
Parameters
first, last - the range of elements to modify
r - the range of elements to modify
value - the value to be assigned
Return value
An output iterator that compares equal to last.

Example
The following code uses ranges::fill to set all elements of std::vector<int> first to -1, then to 10.

Run this code


#include <algorithm>
#include <iostream>
#include <vector>

void println(std::vector<int> const& vi)


{
for (int e : vi)
std::cout << e << ' ';
std::cout << '\n';
}

int main()
{
std::vector<int> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

std::ranges::fill(v.begin(), v.end(), -1);


println(v);

std::ranges::fill(v, 10);
println(v);
}

Output:
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
10 10 10 10 10 10 10 10 10 10
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::generate
Parameters
first, last - the range of elements to modify
r - the range of elements to modify
gen - the generator function object
Return value
An output iterator that compares equal to last.

Example
Run this code
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string_view>

auto dice()
{
static std::uniform_int_distribution<int> distr {1, 6};
static std::random_device device;
static std::mt19937 engine {device()};
return distr(engine);
}

void iota(auto& v, int n)


{
std::ranges::generate(v, [&n]() mutable { return n++; });
}

void print(std::string_view comment, const auto& v)


{
for (std::cout << comment; int i : v)
std::cout << i << ' ';
std::cout << '\n';
}

int main()
{
std::array<int, 8> v;

std::ranges::generate(v.begin(), v.end(), dice);


print("dice: ", v);
std::ranges::generate(v, dice);
print("dice: ", v);

iota(v, 1);
print("iota: ", v);
}

Possible output:
dice: 4 3 1 6 6 4 5 5
dice: 4 2 5 3 6 2 6 2
iota: 1 2 3 4 5 6 7 8

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::remove_copy, std::ranges::remove_copy_if
Parameters
first, last - the source range of elements
r - the source range of elements
result - the beginning of the destination range
value - the value of the elements not to copy
comp - the binary predicate to compare the projected elements
proj - the projection to apply to the elements
Return value
{last, result + N}, where N is the number of elements copied.

Example
Run this code
#include <algorithm>
#include <array>
#include <complex>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string_view>
#include <vector>

void print(const auto rem, const auto& v)


{
std::cout << rem << ' ';
for (const auto& e : v)
std::cout << e << ' ';
std::cout << '\n';
}

int main()
{
// Filter out the hash symbol from the given string.
const std::string_view str{"#Small #Buffer #Optimization"};
std::cout << "before: " << std::quoted(str) << '\n';

std::cout << "after: \"";


std::ranges::remove_copy(str.begin(), str.end(),
std::ostream_iterator<char>(std::cout), '#');
std::cout << "\"\n";

// Copy only the complex numbers with positive imaginary part.


using Ci = std::complex<int>;
constexpr std::array<Ci, 5> source
{
Ci{1, 0}, Ci{0, 1}, Ci{2, -1}, Ci{3, 2}, Ci{4, -3}
};
std::vector<std::complex<int>> target;

std::ranges::remove_copy_if(
source,
std::back_inserter(target),
[](int imag) { return imag <= 0; },
[](Ci z) { return z.imag(); }
);

print("source:", source);
print("target:", target);
}

Output:
before: "#Small #Buffer #Optimization"
after: "Small Buffer Optimization"
source: (1,0) (0,1) (2,-1) (3,2) (4,-3)
target: (0,1) (3,2)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::unique

Parameters
first, last - the range of elements to process
r - the range of elements to process
comp - the binary predicate to compare the projected elements
proj - the projection to apply to the elements
Return value
Returns {ret, last}, where ret is a past-the-end iterator for the new end of the range.

Example
Run this code
#include <algorithm>
#include <cmath>
#include <complex>
#include <iostream>
#include <vector>
struct id {
int i;
explicit id(int i) : i {i} {}
};

void print(id i, const auto& v)


{
std::cout << i.i << ") ";
std::ranges::for_each(v, [](auto const& e) { std::cout << e << ' '; });
std::cout << '\n';
}

int main()
{
// a vector containing several duplicated elements
std::vector<int> v {1, 2, 1, 1, 3, 3, 3, 4, 5, 4};

print(id {1}, v);

// remove consecutive (adjacent) duplicates


const auto ret = std::ranges::unique(v);
// v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate
v.erase(ret.begin(), ret.end());
print(id {2}, v);

// sort followed by unique, to remove all duplicates


std::ranges::sort(v); // {1 1 2 3 4 4 5}
print(id {3}, v);

const auto [first, last] = std::ranges::unique(v.begin(), v.end());


// v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate
v.erase(first, last);
print(id {4}, v);

// unique with custom comparison and projection


std::vector<std::complex<int>> vc { {1, 1}, {-1, 2}, {-2, 3}, {2, 4}, {-3,
5} };
print(id {5}, vc);

const auto ret2 = std::ranges::unique(vc,


// consider two complex nums equal if their real parts are equal by
module:
[](int x, int y) { return std::abs(x) == std::abs(y); }, // comp
[](std::complex<int> z) { return z.real(); } // proj
);
vc.erase(ret2.begin(), ret2.end());
print(id {6}, vc);
}

Output:
1) 1 2 1 1 3 3 3 4 5 4
2) 1 2 1 3 4 5 4
3) 1 1 2 3 4 4 5
4) 1 2 3 4 5
5) (1,1) (-1,2) (-2,3) (2,4) (-3,5)
6) (1,1) (-2,3) (-3,5)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::reverse
Parameters
first, last - the range of elements to reverse
r - the range of elements to reverse
Return value
An iterator equal to last.

Example
Run this code
#include <algorithm>
#include <array>
#include <iostream>
#include <string>

int main()
{
std::string s {"ABCDEF"};
std::cout << s << " → ";
std::ranges::reverse(s.begin(), s.end());
std::cout << s << " → ";
std::ranges::reverse(s);
std::cout << s << " │ ";

std::array a {1, 2, 3, 4, 5};


for (auto e : a)
std::cout << e << ' ';
std::cout << "→ ";
std::ranges::reverse(a);
for (auto e : a)
std::cout << e << ' ';
std::cout << '\n';
}

Output:
ABCDEF → FEDCBA → ABCDEF │ 1 2 3 4 5 → 5 4 3 2 1

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::rotate
Parameters
first, last - the range of elements to rotate
r - the range of elements to rotate
middle - the iterator to the element that should appear at the beginning of the rotated
range
Return value
{new_first, last}, where new_first compares equal to ranges::next(first, ranges::distance(middle,
last)) and designates a new location of the element pointed by first

Example
ranges::rotate is a common building block in many algorithms. This example demonstrates insertion sort.

Run this code


#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>

int main()
{
std::string s(16, ' ');

for (int k {}; k != 5; ++k)


{
std::iota(s.begin(), s.end(), 'A');
std::ranges::rotate(s, s.begin() + k);
std::cout << "Rotate left (" << k << "): " << s << '\n';
}
std::cout << '\n';

for (int k {}; k != 5; ++k)


{
std::iota(s.begin(), s.end(), 'A');
std::ranges::rotate(s, s.end() - k);
std::cout << "Rotate right (" << k << "): " << s << '\n';
}

std::cout << "\nInsertion sort using `rotate`, step-by-step:\n";

s = {'2', '4', '2', '0', '5', '9', '7', '3', '7', '1'};

for (auto i = s.begin(); i != s.end(); ++i)


{
std::cout << "i = " << std::ranges::distance(s.begin(), i) << ": ";
std::ranges::rotate(std::ranges::upper_bound(s.begin(), i, *i), i, i +
1);
std::cout << s << '\n';
}
std::cout << (std::ranges::is_sorted(s) ? "Sorted!" : "Not sorted.") <<
'\n';
}
Output:
Rotate left (0): ABCDEFGHIJKLMNOP
Rotate left (1): BCDEFGHIJKLMNOPA
Rotate left (2): CDEFGHIJKLMNOPAB
Rotate left (3): DEFGHIJKLMNOPABC
Rotate left (4): EFGHIJKLMNOPABCD

Rotate right (0): ABCDEFGHIJKLMNOP


Rotate right (1): PABCDEFGHIJKLMNO
Rotate right (2): OPABCDEFGHIJKLMN
Rotate right (3): NOPABCDEFGHIJKLM
Rotate right (4): MNOPABCDEFGHIJKL

Insertion sort using `rotate`, step-by-step:


i = 0: 2420597371
i = 1: 2420597371
i = 2: 2240597371
i = 3: 0224597371
i = 4: 0224597371
i = 5: 0224597371
i = 6: 0224579371
i = 7: 0223457971
i = 8: 0223457791
i = 9: 0122345779
Sorted!

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::sort
Parameters
first, last - iterator-sentinel defining the range to sort
r - the range to sort
comp - comparison to apply to the projected elements
proj - projection to apply to the elements
Return value
An iterator equal to last.

Example
Run this code
#include <algorithm>
#include <array>
#include <functional>
#include <iomanip>
#include <iostream>

void print(auto comment, auto const& seq, char term = ' ')
{
for (std::cout << comment << '\n'; auto const& elem : seq)
std::cout << elem << term;
std::cout << '\n';
}

struct Particle
{
std::string name; double mass; // MeV
template<class Os> friend
Os& operator<<(Os& os, Particle const& p)
{
return os << std::left << std::setw(8) << p.name << " : " << p.mass <<
' ';
}
};

int main()
{
std::array s {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};

namespace ranges = std::ranges;

ranges::sort(s);
print("Sort using the default operator<", s);

ranges::sort(s, ranges::greater());
print("Sort using a standard library compare function object", s);

struct
{
bool operator()(int a, int b) const { return a < b; }
} customLess;
ranges::sort(s.begin(), s.end(), customLess);
print("Sort using a custom function object", s);

ranges::sort(s, [](int a, int b) { return a > b; });


print("Sort using a lambda expression", s);

Particle particles[]
{
{"Electron", 0.511}, {"Muon", 105.66}, {"Tau", 1776.86},
{"Positron", 0.511}, {"Proton", 938.27}, {"Neutron", 939.57}
};
ranges::sort(particles, {}, &Particle::name);
print("\nSort by name using a projection", particles, '\n');
ranges::sort(particles, {}, &Particle::mass);
print("Sort by mass using a projection", particles, '\n');
}

Output:
Sort using the default operator<
0 1 2 3 4 5 6 7 8 9
Sort using a standard library compare function object
9 8 7 6 5 4 3 2 1 0
Sort using a custom function object
0 1 2 3 4 5 6 7 8 9
Sort using a lambda expression
9 8 7 6 5 4 3 2 1 0

Sort by name using a projection


Electron : 0.511
Muon : 105.66
Neutron : 939.57
Positron : 0.511
Proton : 938.27
Tau : 1776.86

Sort by mass using a projection


Electron : 0.511
Positron : 0.511
Muon : 105.66
Proton : 938.27
Neutron : 939.57
Tau : 1776.86

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::merge
Parameters
first1, last1 - the first input sorted range
first2, last2 - the second input sorted range
result - the beginning of the output range
comp - comparison to apply to the projected elements
proj1 - projection to apply to the elements in the first range
proj2 - projection to apply to the elements in the second range
Return value
{last1, last2, result_last}, where result_last is the end of the constructed range.

Example
Run this code
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

void print(const auto& in1, const auto& in2, auto first, auto last)
{
std::cout << "{ ";
for (const auto& e : in1)
std::cout << e << ' ';
std::cout << "} +\n{ ";
for (const auto& e : in2)
std::cout << e << ' ';
std::cout << "} =\n{ ";
while (!(first == last))
std::cout << *first++ << ' ';
std::cout << "}\n\n";
}

int main()
{
std::vector<int> in1, in2, out;

in1 = {1, 2, 3, 4, 5};


in2 = {3, 4, 5, 6, 7};
out.resize(in1.size() + in2.size());
const auto ret = std::ranges::merge(in1, in2, out.begin());
print(in1, in2, out.begin(), ret.out);

in1 = {1, 2, 3, 4, 5, 5, 5};


in2 = {3, 4, 5, 6, 7};
out.clear();
out.reserve(in1.size() + in2.size());
std::ranges::merge(in1, in2, std::back_inserter(out));
print(in1, in2, out.cbegin(), out.cend());
}

Output:
{ 1 2 3 4 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 6 7 }

{ 1 2 3 4 5 5 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 5 5 6 7 }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::max
Parameters
a, b - the values to compare
r - the range of values to compare
comp - comparison to apply to the projected elements
proj - projection to apply to the elements
Return value
1) The greater of a and b, according to their respective projected values. If they are equivalent,
returns a.
2,3) The greatest value in r, according to the projection. If several values are equivalent to the
greatest, returns the leftmost one. If the range is empty (as determined by ranges::distance(r)),
the behavior is undefined.

Example
Run this code
#include <algorithm>
#include <iostream>
#include <string>

static_assert(std::ranges::max({0B10, 0X10, 010, 10}) == 16); // overload (2)

int main()
{
namespace ranges = std::ranges;
using namespace std::string_view_literals;

std::cout << "larger of 1 and 9999: " << ranges::max(1, 9999) << '\n'
<< "larger of 'a', and 'b': '" << ranges::max('a', 'b') << "'\n"
<< "longest of \"foo\", \"bar\", and \"hello\": \""
<< ranges::max({"foo"sv, "bar"sv, "hello"sv}, {},
&std::string_view::size) << "\"\n";
}

Output:
larger of 1 and 9999: 9999
larger of 'a', and 'b': 'b'
longest of "foo", "bar", and "hello": "hello"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::min
Parameters
a, b - the values to compare
r - the range of values to compare
comp - comparison to apply to the projected elements
proj - projection to apply to the elements
Return value
1) The smaller of a and b, according to the projection. If they are equivalent, returns a.
2,3) The smallest element in r, according to the projection. If several values are equivalent to the
smallest, returns the leftmost one. If the range is empty (as determined by ranges::distance(r)),
the behavior is undefined.

Example
Run this code
#include <algorithm>
#include <iostream>
#include <string>

int main()
{
namespace ranges = std::ranges;
using namespace std::string_view_literals;
std::cout << "smaller of 1 and 9999: " << ranges::min(1, 9999) << '\n'
<< "smaller of 'a', and 'b': '" << ranges::min('a', 'b') << "'\n"
<< "shortest of \"foo\", \"bar\", and \"hello\": \""
<< ranges::min({"foo"sv, "bar"sv, "hello"sv}, {},
&std::string_view::size) << "\"\n";
}

Output:
smaller of 1 and 9999: 1
smaller of 'a', and 'b': 'a'
shortest of "foo", "bar", and "hello": "foo"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
std::ranges::lexicographical_compare

Parameters
first1, last1 - the first range of elements to examine
r1 - the first range of elements to examine
first2, last2 - the second range of elements to examine
r2 - the second range of elements to examine
comp - comparison function to apply to the projected elements
proj1 - projection to apply to the first range of elements
proj2 - projection to apply to the second range of elements
Return value
true if the first range is lexicographically less than the second.

Example
Run this code
#include <algorithm>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>

int main()
{
std::vector<char> v1 {'a', 'b', 'c', 'd'};
std::vector<char> v2 {'a', 'b', 'c', 'd'};

namespace ranges = std::ranges;


auto os = std::ostream_iterator<char>(std::cout, " ");

std::mt19937 g {std::random_device {}()};


while (not ranges::lexicographical_compare(v1, v2))
{
ranges::copy(v1, os);
std::cout << ">= ";
ranges::copy(v2, os);
std::cout << '\n';

ranges::shuffle(v1, g);
ranges::shuffle(v2, g);
}

ranges::copy(v1, os);
std::cout << "< ";
ranges::copy(v2, os);
std::cout << '\n';
}

Possible output:
a b c d >= a b c d
d a b c >= c b d a
b d a c >= a d c b
a c d b < c d a b

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
Std::ranges::iota
Parameters
first, last - the range of elements to fill with sequentially increasing values starting
with value
value - initial value to store; the expression ++value must be well-formed
Return value
{last, value + ranges::distance(first, last)}

Example
Uses the vector of iterators (std::vector<std::list<T>::iterator>) as a proxy to shuffle the
elements of the std::list, because ranges::shuffle cannot be applied to the std::list directly.

Run this code


#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
#include <numeric>
#include <random>
#include <vector>

template <typename Proj = std::identity>


void println(auto comment, std::ranges::input_range auto&& range, Proj proj =
{})
{
for (std::cout << comment; auto const &element : range)
std::cout << proj(element) << ' ';
std::cout << '\n';
}

int main()
{
std::list<int> list(8);

// Fill the list with ascending values: 0, 1, 2, ..., 7


std::ranges::iota(list, 0);
println("List: ", list);

// A vector of iterators (see the comment to Example)


std::vector<std::list<int>::iterator> vec(list.size());

// Fill with iterators to consecutive list's elements


std::ranges::iota(vec.begin(), vec.end(), list.begin());

std::ranges::shuffle(vec, std::mt19937 {std::random_device {}()});


println("List viewed via vector: ", vec, [](auto it) { return *it; });
}

Possible output:
List: 0 1 2 3 4 5 6 7
List viewed via vector: 5 7 6 0 1 3 4 2

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy