Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ranges_example.C File Reference

Example demonstrating C++20 Ranges support in Aleph-w. More...

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <cmath>
#include <tclap/CmdLine.h>
#include <htlist.H>
#include <tpl_dynArray.H>
#include <tpl_dynDlist.H>
#include <ah-ranges.H>
Include dependency graph for ranges_example.C:

Go to the source code of this file.

Functions

void print_section (const string &title)
 
void print_subsection (const string &title)
 
template<typename Container >
void print_container (const string &label, const Container &c)
 
void demo_no_ranges ()
 
int main (int argc, char *argv[])
 

Detailed Description

Example demonstrating C++20 Ranges support in Aleph-w.

This program demonstrates C++20 Ranges support in Aleph-w through ah-ranges.H. Ranges provide a modern, composable way to work with sequences of data using lazy evaluation and the pipe operator (|). This is the C++20 standard way of doing functional programming.

What are C++20 Ranges?

C++20 Ranges introduce:

  • Range concepts: Types that can be iterated
  • Range adaptors: Lazy transformations (views)
  • Pipe operator: Composable operations (range | filter | transform)
  • Lazy evaluation: Values computed on demand

Key advantage: No intermediate allocations until you "materialize" the range into a container.

Key Concepts

Lazy Evaluation

Traditional approach (eager):

auto doubled = map(data, [](int x) { return x * 2; }); // Allocates now
auto filtered = filter(doubled, is_positive); // Allocates again

Ranges approach (lazy):

auto result = data | views::transform(double_it) | views::filter(is_positive);
// No allocation yet! Just a view.
auto vec = result | ranges::to<vector>(); // Materialize when needed

Range Adaptors

Transform ranges without creating new containers:

  • **views::filter**: Keep elements satisfying predicate
  • **views::transform**: Transform each element
  • **views::take**: Take first n elements
  • **views::drop**: Skip first n elements
  • **views::reverse**: Reverse order

Views

Views are:

  • Non-owning: Don't own the underlying data
  • Composable: Can chain multiple views
  • Lazy: Computed on demand
  • Zero-cost: No allocation until materialized

Pipe Syntax

The pipe operator (|) allows natural composition:

auto result = data
| views::filter(is_positive)
| views::transform(square)
| views::take(10)
| ranges::to<vector>();

Reads like: "Take data, filter positives, square them, take 10, convert to vector"

Comparison with Traditional Approach

Aspect Traditional C++20 Ranges
Evaluation Eager (immediate) Lazy (on demand)
Memory Multiple allocations Single allocation (at end)
Syntax Nested calls Pipe composition
Performance Can be slower Often faster (fewer allocations)

Requirements

  • C++20: Requires -std=c++20 compiler flag
  • Compiler: GCC 12+ or Clang 16+ with libc++
  • Standard library: C++20 ranges support

Benefits

Performance

  • Fewer allocations: Only materialize at the end
  • Better cache usage: Composed operations can be optimized
  • Compiler optimizations: Modern compilers optimize range pipelines

Readability

  • Natural flow: Left-to-right reading
  • Composable: Easy to add/remove operations
  • Declarative: Describe what you want, not how

Memory Efficiency

  • Lazy evaluation: Don't create intermediate containers
  • Views: Non-owning, zero overhead
  • Materialization: Only when you need the result

Usage Examples

# Run all range demonstrations
./ranges_example
# Run specific demo
./ranges_example -s lazy # Lazy evaluation demo
./ranges_example -s views # Views and adaptors demo
./ranges_example -s materialize # Materialization demo
./ranges_example -s aleph # Aleph containers with ranges demo
./ranges_example -s practical # Practical examples
./ranges_example -s perf # Performance demo
# Show help
./ranges_example --help

Example Pipeline

// Process large dataset efficiently
auto result = large_dataset
| views::filter([](auto x) { return x > 0; }) // Lazy filter
| views::transform([](auto x) { return x * 2; }) // Lazy transform
| views::take(1000) // Lazy take
| ranges::to<vector>(); // Materialize once

Only one allocation (at the end), not three intermediate allocations!

See also
ah-ranges.H C++20 Ranges support for Aleph containers
functional_example.C Traditional functional utilities (eager)
uni_functional_example.C Unified functional (works with both)
Author
Leandro Rabindranath León
Date
2024

Definition in file ranges_example.C.

Function Documentation

◆ demo_no_ranges()

void demo_no_ranges ( )

Definition at line 496 of file ranges_example.C.

References Aleph::maps(), and print_section().

Referenced by main().

◆ main()

int main ( int  argc,
char *  argv[] 
)

◆ print_container()

template<typename Container >
void print_container ( const string &  label,
const Container c 
)

Definition at line 173 of file ranges_example.C.

References Aleph::maps().

◆ print_section()

void print_section ( const string &  title)

Definition at line 160 of file ranges_example.C.

References Aleph::maps().

Referenced by demo_no_ranges().

◆ print_subsection()

void print_subsection ( const string &  title)

Definition at line 167 of file ranges_example.C.

References Aleph::maps().