CodeNebula
C++17stladvanced

std::for_each_n

C++17 · Practical Modern · Compiler flag: -std=c++17

Explanation

Applies a function to exactly the first `n` elements of a range, returning an iterator past the last processed element. It is safer than manually computing an end iterator for partial range operations.

Real-World Scenario

Process the first `n` highest-priority tasks from a sorted task queue.

Quick Snippet

snippet.cpp
#include <algorithm>
#include <vector>

std::vector<int> tasks = {10, 20, 30, 40, 50};
std::for_each_n(tasks.begin(), 3, [](int& t) {
    std::cout << "Processing task " << t << "\n";
});

Full Example

for_each_n.cpp
// CodeNebula - C++17 Example: std::for_each_n
// Compile: g++ -std=c++17 -Wall -Wextra -o example for_each_n.cpp

// Demonstrates std::for_each_n, which applies a function to the first N
// elements of a range. Unlike std::for_each, you specify a count instead
// of an end iterator -- useful when you only want to process a prefix.

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

int main()
{
    // ------------------------------------------------------------------
    // 1. Basic usage: print first N elements
    // ------------------------------------------------------------------
    std::cout << "=== print first N elements ===" << std::endl;
    std::vector<int> nums = {10, 20, 30, 40, 50, 60, 70, 80};

    std::cout << "  All: ";
    for (int n : nums) std::cout << n << " ";
    std::cout << std::endl;

    std::cout << "  First 4: ";
    std::for_each_n(nums.begin(), 4, [](int n) {
        std::cout << n << " ";
    });
    std::cout << std::endl;

    // ------------------------------------------------------------------
    // 2. Modify first N elements
    // ------------------------------------------------------------------
    std::cout << "\n=== modify first N ===" << std::endl;
    std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8};
    std::cout << "  Before: ";
    for (int x : data) std::cout << x << " ";
    std::cout << std::endl;

    // Double the first 3 elements
    std::for_each_n(data.begin(), 3, [](int& x) { x *= 2; });
    std::cout << "  After (first 3 doubled): ";
    for (int x : data) std::cout << x << " ";
    std::cout << std::endl;

    // ------------------------------------------------------------------
    // 3. Return value: iterator past the last processed element
    // ------------------------------------------------------------------
    std::cout << "\n=== return value ===" << std::endl;
    std::vector<int> v = {100, 200, 300, 400, 500};
    auto it = std::for_each_n(v.begin(), 3, [](int n) {
        std::cout << "  processed: " << n << std::endl;
    });
    std::cout << "  Next element after processed range: " << *it << std::endl;

    // ------------------------------------------------------------------
    // 4. With strings
    // ------------------------------------------------------------------
    std::cout << "\n=== string processing ===" << std::endl;
    std::vector<std::string> words = {"alpha", "beta", "gamma", "delta", "epsilon"};

    std::cout << "  First 3 uppercased:" << std::endl;
    std::for_each_n(words.begin(), 3, [](std::string& w) {
        for (char& c : w) c = static_cast<char>(std::toupper(c));
    });
    for (const auto& w : words) std::cout << "    " << w << std::endl;

    // ------------------------------------------------------------------
    // 5. Accumulate using for_each_n (stateful lambda)
    // ------------------------------------------------------------------
    std::cout << "\n=== stateful lambda (sum first N) ===" << std::endl;
    std::vector<int> scores = {95, 87, 92, 78, 85, 91, 88};
    int sum = 0;
    int count = 5;
    std::for_each_n(scores.begin(), count, [&sum](int s) { sum += s; });
    std::cout << "  Sum of first " << count << " scores: " << sum << std::endl;
    std::cout << "  Average: " << static_cast<double>(sum) / count << std::endl;

    // ------------------------------------------------------------------
    // 6. N = 0 is safe (no-op)
    // ------------------------------------------------------------------
    std::cout << "\n=== N=0 (no-op) ===" << std::endl;
    std::for_each_n(nums.begin(), 0, [](int) {
        std::cout << "  This should never print" << std::endl;
    });
    std::cout << "  for_each_n with N=0 did nothing (as expected)" << std::endl;

    return 0;
}

/*
Expected output:

=== print first N elements ===
  All: 10 20 30 40 50 60 70 80
  First 4: 10 20 30 40

=== modify first N ===
  Before: 1 2 3 4 5 6 7 8
  After (first 3 doubled): 2 4 6 4 5 6 7 8

=== return value ===
  processed: 100
  processed: 200
  processed: 300
  Next element after processed range: 400

=== string processing ===
  First 3 uppercased:
    ALPHA
    BETA
    GAMMA
    delta
    epsilon

=== stateful lambda (sum first N) ===
  Sum of first 5 scores: 437
  Average: 87.4

=== N=0 (no-op) ===
  for_each_n with N=0 did nothing (as expected)
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example for_each_n.cpp