Daily bit(e) C++. std::transform

Добавлено 22 сентября 2026 в 06:53

Daily bit(e) C++ 115, алгоритм «копирования с преобразованием» – std::transform.

Daily bit(e) C++

Алгоритм std::transform позволяет копировать элементы из одного диапазона в другой, применяя к каждому элементу определенное преобразование. Это преобразование может изменять тип элементов результирующего диапазона.

У данного алгоритма также есть бинарная версия, которую можно использовать для объединения двух диапазонов в один.

Выходной диапазон может совпадать с одним из входных диапазонов (но не может быть смещен относительно него); однако, если преобразование выполняется «на месте» (in-place), предпочтительнее использовать цикл for на основе диапазона или std::for_each.

Для обоих вариантов доступны версии с поддержкой параллельного выполнения (начиная с C++17) и работы с диапазонами (начиная с C++20).

#include <algorithm>
#include <string>
#include <cctype>
#include <vector>
#include <iterator>

// Копирование с преобразованием:
std::vector<int> in{1, 2, 3, 4, 5, 6, 7};
std::vector<double> out;

std::transform(in.begin(), in.end(),
    std::back_inserter(out),
    [](int v) { return static_cast<double>(v)/2; });
// out ~= {0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5}


// Объединение двух диапазонов в один:
std::vector<int> in1{1, 2, 3, 4, 5};
std::vector<int> in2{0, 1, 0, 1, 0};
std::vector<int> reduction;

std::transform(in1.begin(), in1.end(), // первый диапазон
    in2.begin(), // второй диапазон, количество элементов из первого диапазона
    std::back_inserter(reduction),
    [](int e1, int e2) { return e1*e2; });
// reduction == {0, 2, 0, 4, 0}


// Выходной диапазон может быть одним из входных диапазонов:
std::string str = "welcome to somewhere";
std::transform(str.begin(), str.end(), // входной диапазон
    str.begin(), // Внимание, смещения не может быть
                 // (только r1.begin(), r2.begin())
    [](char c) { return std::toupper(c); });
// str == "WELCOME TO SOMEWHERE"


// Соблюдайте осторожность при работе с типами,
// копирование которых обходится дорого.
struct Expensive{};
std::vector<Expensive> data(10);
std::transform(data.begin(), data.end(),
    data.begin(),
    [](const Expensive& v) { return v; }); // копирование
// Для изменения элементов "на месте", используйте std::for_each
// или цикл for на основе диапазона.


// В случае с версией для диапазонов, мы можем
// разбить преобразование на два этапа
std::vector<int> two_digit;
std::ranges::transform(in1, in2,
    std::back_inserter(two_digit),
    std::plus<>{},                // объединение
    [](int v) { return v * 10; }, // проекция in1
    std::identity{});             // проекция in2
// two_digit == {10, 21, 30, 41, 50}

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование