std::transform în C++

Aplică o funcție fiecărui element și scrie rezultatele în alt interval (sau în același).

Sintaxă
OutputIt transform(InputIt first, InputIt last, OutputIt d_first, UnaryOp op);
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOp op);

Ce face std::transform

std::transform calculează op(element) pentru fiecare element și scrie rezultatul la destinația d_first. Destinația poate fi chiar începutul intervalului sursă, pentru transformare pe loc.

Varianta cu două intervale combină elemente aflate pe aceeași poziție: op(a[i], b[i]). Destinația trebuie să aibă destul loc; altfel folosește std::back_inserter.

Parametri

Parametru Descriere
first, last Intervalul sursă.
first2 Pentru varianta binară: începutul celui de-al doilea interval (cel puțin la fel de lung).
d_first Unde se scriu rezultatele.
op Funcția aplicată.

Ce returnează

Iterator după ultimul element scris.

Exemple

Exemplul 1: Text cu majuscule

Transformare pe loc: sursa și destinația sunt același șir.

#include <algorithm>
#include <cctype>
#include <print>
#include <string>

int main() {
    std::string oras = "cluj-napoca";
    std::transform(oras.begin(), oras.end(), oras.begin(),
                   [](unsigned char c) { return static_cast<char>(std::toupper(c)); });
    std::println("{}", oras);
}

Rezultat

CLUJ-NAPOCA

Exemplul 2: Prețuri cu TVA într-un vector nou

std::back_inserter adaugă fiecare rezultat la final cu push_back.

#include <algorithm>
#include <iterator>
#include <print>
#include <vector>

int main() {
    std::vector<double> fara_tva{100.0, 49.9, 15.0};
    std::vector<double> cu_tva;

    std::transform(fara_tva.begin(), fara_tva.end(), std::back_inserter(cu_tva),
                   [](double p) { return p * 1.21; });

    for (double p : cu_tva) {
        std::println("{:.2f}", p);
    }
}

Rezultat

121.00
60.38
18.15

Exemplul 3: Două intervale: cantitate × preț

#include <algorithm>
#include <print>
#include <vector>

int main() {
    std::vector<int> cantitati{2, 5, 1};
    std::vector<int> preturi{30, 4, 120};
    std::vector<int> totaluri(cantitati.size());

    std::transform(cantitati.begin(), cantitati.end(), preturi.begin(), totaluri.begin(),
                   [](int c, int p) { return c * p; });
    std::println("{}", totaluri);
}

Rezultat

[60, 20, 120]

Greșeli frecvente

  • Scrii într-un vector gol fără back_inserter: std::transform(..., rezultat.begin(), ...) cu rezultat gol scrie în afara memoriei (comportament nedefinit).
  • Dai lui std::toupper un char cu semn: literele cu diacritice au coduri negative și comportamentul este nedefinit. Convertește la unsigned char.

Comenzi înrudite

  • std::for_each: Aplică o funcție fiecărui element dintr-un interval, de exemplu pentru afișare sau modificare.
  • std::views::transform: Creează o vedere în care fiecare element este rezultatul unei funcții aplicate elementului original.
  • std::copy: Copiază elementele unui interval (copy) sau primele n elemente (copy_n) la o destinație.
  • std::accumulate: Adună toate elementele unui interval pornind de la o valoare inițială (sau le combină cu o operație dată).