- Use `std::views::filter` and `std::views::transform` with the pipe operator (`|`) to compose lazy data pipelines — they process elements on demand without intermediate allocations.
- Prefer range-based algorithms (`std::ranges::sort`, `std::ranges::find`) over their `<algorithm>` counterparts — they accept ranges directly and provide better error messages.
- Use `std::views::iota(0, n)` to generate index sequences — replace manual `for (int i = 0; i < n; ++i)` loops with range-for over iota views.
- Compose views with the pipe operator for readability: `data | filter(pred) | transform(fn) | take(10)` reads left-to-right like a data pipeline.
- Use `std::views::zip` (C++23) or `ranges::views::zip` to iterate multiple ranges in lockstep without manual index management.
- Use `std::ranges::to<Container>()` (C++23) to materialize a view into a concrete container — avoid manual `std::vector` construction from view iterators.
- Prefer `std::views::split` and `std::views::join` for string tokenization and concatenation over manual `find`/`substr` loops.