C++20stladvanced
std::ranges::bidirectional_range (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
Concept for ranges whose iterators can move both forward and backward. Required by algorithms like `reverse` and `partition` that need to traverse from both ends.
Real-World Scenario
Traverse a playlist forward and backward in a media player's queue system.
Quick Snippet
snippet.cpp
#include <ranges>
template<std::ranges::bidirectional_range R>
void reverse_in_place(R&& r) {
auto first = std::ranges::begin(r);
auto last = std::ranges::end(r);
while (first != last && first != --last)
std::ranges::iter_swap(first++, last);
}Full Example
ranges_bidirectional_range.cpp
// CodeNebula - C++20 Example: std::ranges::bidirectional_range Concept
// Compile: g++ -std=c++20 -Wall -Wextra -o example ranges_bidirectional_range.cpp
#include <ranges>
#include <vector>
#include <list>
#include <forward_list>
#include <iostream>
// std::ranges::bidirectional_range requires that iterators support
// both increment (++) and decrement (--) operations.
// Print a range in reverse using bidirectional iterators
template <std::ranges::bidirectional_range R>
void print_reversed(const R& r) {
auto it = std::ranges::end(r);
auto begin = std::ranges::begin(r);
while (it != begin) {
--it;
std::cout << *it << " ";
}
std::cout << "\n";
}
// Check if a bidirectional range is a palindrome efficiently
template <std::ranges::bidirectional_range R>
requires std::equality_comparable<std::ranges::range_value_t<R>>
bool is_palindrome(const R& r) {
auto front = std::ranges::begin(r);
auto back = std::ranges::end(r);
if (front == back) return true;
--back;
while (front != back) {
if (*front != *back) return false;
++front;
if (front == back) break;
--back;
}
return true;
}
int main() {
// Bidirectional containers
static_assert(std::ranges::bidirectional_range<std::vector<int>>);
static_assert(std::ranges::bidirectional_range<std::list<int>>);
// forward_list is NOT bidirectional
static_assert(!std::ranges::bidirectional_range<std::forward_list<int>>);
std::vector<int> nums = {1, 2, 3, 4, 5};
std::cout << "Original: ";
for (int n : nums) std::cout << n << " ";
std::cout << "\nReversed: ";
print_reversed(nums);
std::list<char> chars = {'r', 'a', 'c', 'e', 'c', 'a', 'r'};
std::cout << "racecar is palindrome: " << std::boolalpha
<< is_palindrome(chars) << "\n";
std::list<int> not_palin = {1, 2, 3, 4};
std::cout << "{1,2,3,4} is palindrome: "
<< is_palindrome(not_palin) << "\n";
// reverse_view requires bidirectional_range
auto rev = nums | std::views::reverse;
std::cout << "Reverse view: ";
for (int n : rev) std::cout << n << " ";
std::cout << "\n";
return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_bidirectional_range.cpp