TGViewer
Библиотека C/C++ разработчика | cpp, boost, qt Библиотека C/C++ разработчика | cpp, boost, qt @cppproglib · 16.9K subscribers
Post #6627 1.86K
🍙 views::transform — ленивые преобразования в C++20

Если views::filter решает, какие элементы обработать, то views::transform — во что их превратить. Никакого копирования: это такая же ленивая обёртка над данными.

🌸 Базовое использование

#include <ranges>
#include <vector>
#include <string>
namespace views = std::views;

std::vector<std::string> words = {"hello", "world", "cpp"};

// Получаем длины слов
auto lengths = words | views::transform([](const std::string& s) {
return s.size();
});
// При итерации: 5, 5, 3


Лямбда применяется к каждому элементу в момент итерации — ни раньше, ни позже.

🍪 Трансформация с изменением типа

transform не обязан возвращать тот же тип. Из string можно получить size_t, из doubleint, из структуры — одно из её полей:

// Верхний регистр (#include <cctype>)
auto upper = words | views::transform([](std::string s) {
for (char& c : s) c = std::toupper(c);
return s;
});
// При итерации: "HELLO", "WORLD", "CPP"


Обратите внимание: здесь s принимается по значению — это намеренная копия, которую мы модифицируем.


🍀 filter + transform — классика

Главная сила адаптеров — в их цепочке. Сначала отсеиваем ненужное, потом преобразуем то, что осталось:

struct Employee {
std::string name;
double salary;
bool is_active;
};

std::vector<Employee> employees = {
{"Алиса", 80000, true},
{"Борис", 95000, false},
{"Виктор", 72000, true},
{"Галина", 110000, true},
};

// Имена активных сотрудников с зарплатой выше 75 000
auto high_earners = employees
| views::filter([](const Employee& e) { return e.is_active; })
| views::filter([](const Employee& e) { return e.salary > 75000; })
| views::transform([](const Employee& e) { return e.name; });

for (const auto& name : high_earners) {
std::cout << name << "\n"; // Алиса, Галина
}


Весь конвейер ленив: ни одна лямбда не вызывается, пока не начнётся итерация.


🌱 pipe-синтаксис vs явный тип

auto v1 = words | views::transform([](const std::string& s) { return s.size(); });
auto v2 = std::ranges::transform_view{words, [](const std::string& s) { return s.size(); }};



🍙 Материализация в вектор

transform_view — не контейнер. Чтобы получить std::vector, нужно явно материализовать:

// C++23
auto vec = words | views::transform([](const std::string& s) { return s.size(); })
| std::ranges::to<std::vector>();

// C++20
std::vector<size_t> vec(lengths.begin(), lengths.end());



Ловушка: несовпадение типа возврата

// UB — возвращается ссылка на временный объект
auto bad = words | views::transform([](const std::string& s) -> const std::string& {
std::string upper = s;
return upper; // dangling reference!
});

// Правильно — возвращаем по значению
auto ok = words | views::transform([](const std::string& s) {
std::string upper = s;
for (char& c : upper) c = std::toupper(c);
return upper;
});



🐸 Продолжение следует...

📍Навигация: ВакансииЗадачиСобесы

Библиотека C/C++ разработчика

#константная_правильность
  • 🥰 4
  • 👍 2
  • 🤔 2
  • 🥱 1
More from @cppproglib
  1. Sep 19, 2026А вы уже забрали свой подарок ко Дню программиста? К вашему профессиональному празднику Tp…
  2. Sep 18, 2026От исходного кода до процессора: разберись, как работает программа 💻 Стартует практически…
  3. Sep 15, 2026😭 Как не потратить недельный лимит AI-кодинга за три дня? Разберём на вебинаре, как трати…
  4. Sep 13, 2026🤪 Если бы можно было задать один вопрос про AI в разработке — что бы вы спросили? Как выб…
  5. Sep 13, 2026🤩 Inline static в классах — забудь про .cpp Сколько раз ты забывал добавить определение s…
  6. Sep 13, 2026🌸 Вселенная намекает: пора уже начать этот курс С 14 сентября цены в Proglib Academy выра…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →