Build With Abdallah logo Build With Abdallah Software · AI · Automation
Tutorial 2 min read Jun 08, 2026

Mastering C++26's Enhanced Ranges with Visual Studio 2026

C++26 introduces enhanced ranges, a feature that simplifies and optimizes the way we work with collections. With these enhancements, developers can write cleaner, more efficient co

A
Abdallah Mohamed
Senior Full-Stack Engineer
Mastering C++26's Enhanced Ranges with Visual Studio 2026

Mastering C++26's Enhanced Ranges with Visual Studio 2026

C++26 introduces enhanced ranges, a feature that simplifies and optimizes the way we work with collections. With these enhancements, developers can write cleaner, more efficient code. This tutorial will guide you through setting up your environment using Visual Studio 2026 and demonstrate how to utilize these new features in practical applications.

Prerequisites

Before you start, ensure your system meets the following requirements and has the necessary tools installed:

  • Operating System: Windows 10 or later
  • Visual Studio 2026: Make sure you have the latest version installed.

To install Visual Studio 2026 with the necessary C++ components, use the Visual Studio Installer:

  1. Download the Visual Studio Installer from Visual Studio's official website.
  2. Launch the installer and select the "Desktop development with C++" workload.
  3. Ensure the "C++20/23/26 support" component is selected.

Project Structure

Before we begin coding, let's set up a simple project structure:

cpp26-enhanced-ranges/
├── src/
│   ├── main.cpp
└── CMakeLists.txt

Step 1: Setting Up the Project with CMake

First, we need to create a basic CMake project to manage our build process. CMake allows us to define the build configuration in a platform-independent manner.

Create a CMakeLists.txt file in the root directory:

cmake_minimum_required(VERSION 3.20)
project(Cpp26EnhancedRanges)

set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(Cpp26EnhancedRanges src/main.cpp)

This CMake configuration specifies that we are using C++26 and defines an executable target named Cpp26EnhancedRanges from the main.cpp file.

Step 2: Implementing a Basic Range Example

Let's write a simple program in main.cpp to demonstrate the basic usage of enhanced ranges.

Create a main.cpp file in the src directory:

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

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

    auto even_numbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });

    std::cout << "Even numbers: ";
    for (int n : even_numbers) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation

  • #include <ranges>: This header is required to use the ranges library.
  • std::views::filter: A view that filters elements based on a predicate. Here, it filters out odd numbers.
  • auto even_numbers: A lazy range that filters numbers for even values.

This code snippet demonstrates how to filter a collection using enhanced ranges.

Step 3: Composing Ranges with Transformations

Now, we'll extend our program to include a transformation. This will showcase how to chain range operations.

Modify main.cpp to include a transformation:

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

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

    auto processed_numbers = numbers 
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; });

    std::cout << "Processed numbers: ";
    for (int n : processed_numbers) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation

  • std::views::transform: This view applies a transformation to each element. In this case, it squares each even number.
  • Chaining Operations: The | operator is used to chain multiple range operations, allowing for concise and expressive code.

This step demonstrates the power of composing range transformations, making it easier to perform complex operations on collections.


## Step 4: Using Range Adaptors for Custom Views

In this step, we'll explore how to create custom range adaptors to further manipulate our collections. Custom adaptors allow us to encapsulate complex operations into reusable components.

Modify `main.cpp` to include a custom range adaptor:

```cpp
#include <iostream>
#include <ranges>
#include <vector>

auto square_if_even = [](int n) -> std::optional<int> {
    if (n % 2 == 0) {
        return n * n;
    }
    return std::nullopt;
};

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

    auto custom_view = numbers 
        | std::views::transform(square_if_even)
        | std::views::filter([](const std::optional<int>& n) { return n.has_value(); })
        | std::views::transform([](const std::optional<int>& n) { return n.value(); });

    std::cout << "Custom view numbers: ";
    for (int n : custom_view) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation

  • std::optional<int>: Used to represent a value that might be absent. This is useful for filtering operations that may not produce a result for every input.
  • Custom Adaptor: square_if_even returns a squared value only for even numbers, encapsulated in an std::optional.

This demonstrates creating a custom view that combines filtering and transformation into a single, reusable operation.

Step 5: Integrating with Standard Algorithms

Enhanced ranges can be integrated with standard algorithms to further streamline operations on collections. Let's see how to do this.

Modify main.cpp to use a standard algorithm:

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

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

    auto even_squares = numbers 
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; });

    std::vector<int> result;
    std::ranges::copy(even_squares, std::back_inserter(result));

    std::cout << "Even squares copied to result: ";
    for (int n : result) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation

  • std::ranges::copy: This algorithm copies elements from a range to another container, demonstrating interoperability between ranges and standard algorithms.
  • std::back_inserter: Used to append elements to the end of result.

This step shows how to effectively use enhanced ranges with existing algorithms to perform complex operations.

Complete Working Example

Here is the complete main.cpp file incorporating all the steps:

#include <iostream>
#include <ranges>
#include <vector>
#include <algorithm>
#include <optional>

auto square_if_even = [](int n) -> std::optional<int> {
    if (n % 2 == 0) {
        return n * n;
    }
    return std::nullopt;
};

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

    auto custom_view = numbers 
        | std::views::transform(square_if_even)
        | std::views::filter([](const std::optional<int>& n) { return n.has_value(); })
        | std::views::transform([](const std::optional<int>& n) { return n.value(); });

    std::vector<int> result;
    std::ranges::copy(custom_view, std::back_inserter(result));

    std::cout << "Custom view numbers copied to result: ";
    for (int n : result) {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}

Common Errors and Fixes

  1. Error: ranges header not found

    Fix: Ensure your compiler supports C++26 and that you have included the correct header files. Update your compiler if necessary.

  2. Error: std::optional not recognized

    Fix: Make sure to include the <optional> header at the beginning of your file.

  3. Error: std::views::filter or std::views::transform not compiling

    Fix: Check that your compiler version supports the C++26 standard and that the CMakeLists.txt specifies CMAKE_CXX_STANDARD 26.

Conclusion

C++26's enhanced ranges provide a powerful way to work with collections, allowing for concise and expressive code. By using range adaptors and integrating with standard algorithms, developers can write cleaner and more efficient code. This tutorial covered setting up a project, creating custom views, and using standard algorithms with enhanced ranges.

Sources