Range-v3 в C++

Kate

Administrator
Команда форума
Сегодня рассмотрим Range-v3 — библиотеку, которая изменила подход к обработке последовательностей в C++ и стала основой для std::ranges в C++20.

Range-v3 — это библиотека, расширяющая стандартную библиотеку C++ возможностью работать с диапазонами вместо begin()/end(). В основе идеи лежат три концепции:

  1. Views — ленивые представления данных
  2. Actions — eager-операции над контейнерами
  3. Pipeline (|) — декларативный синтаксис для обработки последовательностей

Почему Range-v3 может быть лучше стандартных алгоритмов?​

Допустим, есть стандартный код на std::algorithm:

std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// Фильтрация + преобразование
std::vector<int> filtered;
std::copy_if(data.begin(), data.end(), std::back_inserter(filtered),
[](int i) { return i % 2 == 0; });

std::vector<int> transformed;
std::transform(filtered.begin(), filtered.end(), std::back_inserter(transformed),
[](int i) { return i * i; });

for (int x : transformed) {
std::cout << x << " ";
}
Проблема:

  1. Куча промежуточных контейнеров filtered, transformed → лишние аллокации
  2. Много boilerplate кода → std::copy_if + std::transform
  3. Можно забыть std::back_inserter и получить UB
А теперь на Range-v3:

#include <iostream>
#include <vector>
#include <range/v3/all.hpp>

int main() {
using namespace ranges;

std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

auto rng = data
| views::filter([](int i) { return i % 2 == 0; }) // Оставляем чётные
| views::transform([](int i) { return i * i; }); // Возводим в квадрат

for (int x : rng) std::cout << x << " ";
}
Теперь у нас нет промежуточных векторов, никакого std::copy_if. Код читается сверху вниз, легко понять логику. Работает лениво и элементы вычисляются только при for

Вывод:

4 16 36 64 100

Как это работает?​

Когда пишем:

auto rng = data | views::filter([](int i) { return i % 2 == 0; });
происходит следующее:

  1. Создаётся ленивый View, который не делает никаких вычислений сразу
  2. rng хранит ссылку на data + фильтрующую лямбду
  3. При итерации по rng:
    • Вызывается operator++
    • Проверяется filter
    • Неподходящие элементы пропускаются
Некоторые views копируют контейнер. Например:

auto rng = views::transform(data, [](int x) { return x * 2; }); // data копируется!
Ошибка: data передаётся по значению!

Правильный вариант:

auto rng = views::all(data) | views::transform([](int x) { return x * 2; });
Теперь data не копируется.

Actions​

Если Views ленивы, то Actions сразу модифицируют контейнер.

Пример сортировки и удаления дубликатов одной цепочкой:

#include <iostream>
#include <vector>
#include <range/v3/all.hpp>

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

data |= ranges::actions::sort | ranges::actions::unique;

for (int x : data) std::cout << x << " ";
}
Выход:

1 2 3 4 5
actions::sort сортирует контейнер, actions::unique удаляет дубликаты

Альтернативный вариант (без |=):

std::vector<int> result = data | actions::sort | actions::unique;
Но он требует копирования.

Как писать свой кастомный View?​

Допустим, нужен views::pow, который возводит элементы в степень. Стандартные views::transform работают, но это некрасиво.

Сделаем свой View, который будет читаться так:

auto rng = data | views::pow(3); // Возводим всё в куб
Создадим адаптер. Любой View в Range-v3 строится через view_adaptor. Это базовый класс, который управляет итерацией.

#include <range/v3/view/adaptor.hpp>
#include <cmath>

struct pow_view : ranges::view_adaptor<pow_view, ranges::view_base> {
friend ranges::range_access;

int power_;

explicit pow_view(int p) : power_(p) {}

// Магия: возведение в степень при итерации
template<typename It>
auto read(It it) const { return std::pow(*it, power_); }
};

// Удобный адаптер
auto pow(int p) { return pow_view{p}; }

Этот pow_view работает как views::transform, но нагляднее.

Теперь кастомный View можно использовать точно так же, как стандартные.

#include <iostream>
#include <vector>
#include <range/v3/all.hpp>

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

auto rng = data | pow(3); // Возводим в куб

for (int x : rng) std::cout << x << " ";
}
Выход:

1 8 27 64 125
В проде View должен уметь работать с разными контейнерами. Добавим поддержку любой последовательности.

template <typename Rng>
struct pow_view : ranges::view_adaptor<pow_view<Rng>, Rng> {
friend ranges::range_access;

int power_;

explicit pow_view(Rng rng, int p) : pow_view::view_adaptor(std::move(rng)), power_(p) {}

// Возводим в степень
auto read(auto it) const { return std::pow(*it, power_); }
};

// Обёртка для удобного использования
template <typename Rng>
auto pow(Rng &&rng, int p) {
return pow_view<Rng>{std::forward<Rng>(rng), p};
}
Теперь это работает с любыми контейнерами:

std::list<double> numbers = {1.5, 2.0, 3.7, 4.1};

auto rng = pow(numbers, 2); // Возведение в квадрат
Теперь поддерживаем и std::list, и std::vector, и std::set!

Подробнее про Range-v3 можно посмотреть здесь.


12 февраля пройдет открытый урок «Отладка в С++. Место в жизненном цикле разработки», на котором:

- узнаете, как использовать отладчик GNU (GDB) для эффективной отладки программ на C++;
- научитесь выявлять и устранять проблемы, связанные с памятью в C++;
- разберетесь с понятием неопределенного поведения в C++ и с тем как его отладить;
- научитесь читать и интерпретировать трассировки стека, чтобы быстро определять местоположение ошибок.

 

yinsushi

Active member
http://audiobookkeeper.ruhttp://cottagenet.ruhttp://eyesvision.ruhttp://eyesvisions.comhttp://factoringfee.ruhttp://filmzones.ruhttp://gadwall.ruhttp://gaffertape.ruhttp://gageboard.ruhttp://gagrule.ruhttp://gallduct.ruhttp://galvanometric.ruhttp://gangforeman.ruhttp://gangwayplatform.ruhttp://garbagechute.ruhttp://gardeningleave.ruhttp://gascautery.ruhttp://gashbucket.ruhttp://gasreturn.ruhttp://gatedsweep.ruhttp://gaugemodel.ruhttp://gaussianfilter.ruhttp://gearpitchdiameter.ruhttp://geartreating.ruhttp://generalizedanalysis.ru http://generalprovisions.ruhttp://geophysicalprobe.ruhttp://geriatricnurse.ruhttp://getintoaflap.ruhttp://getthebounce.ruhttp://habeascorpus.ruhttp://habituate.ruhttp://hackedbolt.ruhttp://hackworker.ruhttp://hadronicannihilation.ruhttp://haemagglutinin.ruhttp://hailsquall.ruhttp://hairysphere.ruhttp://halforderfringe.ruhttp://halfsiblings.ruhttp://hallofresidence.ruhttp://haltstate.ruhttp://handcoding.ruhttp://handportedhead.ruhttp://handradar.ruhttp://handsfreetelephone.ruhttp://hangonpart.ruhttp://haphazardwinding.ruhttp://hardalloyteeth.ruhttp://hardasiron.ru http://hardenedconcrete.ruhttp://harmonicinteraction.ruhttp://hartlaubgoose.ruhttp://hatchholddown.ruhttp://haveafinetime.ruhttp://hazardousatmosphere.ruhttp://headregulator.ruhttp://heartofgold.ruhttp://heatageingresistance.ruhttp://heatinggas.ruhttp://heavydutymetalcutting.ruhttp://jacketedwall.ruhttp://japanesecedar.ruhttp://jibtypecrane.ruhttp://jobabandonment.ruhttp://jobstress.ruhttp://jogformation.ruhttp://jointcapsule.ruhttp://jointsealingmaterial.ruhttp://journallubricator.ruhttp://juicecatcher.ruhttp://junctionofchannels.ruhttp://justiciablehomicide.ruhttp://juxtapositiontwin.ruhttp://kaposidisease.ru http://keepagoodoffing.ruhttp://keepsmthinhand.ruhttp://kentishglory.ruhttp://kerbweight.ruhttp://kerrrotation.ruhttp://keymanassurance.ruhttp://keyserum.ruhttp://kickplate.ruhttp://killthefattedcalf.ruhttp://kilowattsecond.ruhttp://kingweakfish.ruhttp://kinozones.ruhttp://kleinbottle.ruhttp://kneejoint.ruhttp://knifesethouse.ruhttp://knockonatom.ruhttp://knowledgestate.ruhttp://kondoferromagnet.ruhttp://labeledgraph.ruhttp://laborracket.ruhttp://labourearnings.ruhttp://labourleasing.ruhttp://laburnumtree.ruhttp://lacingcourse.ruhttp://lacrimalpoint.ru http://lactogenicfactor.ruhttp://lacunarycoefficient.ruhttp://ladletreatediron.ruhttp://laggingload.ruhttp://laissezaller.ruhttp://lambdatransition.ruhttp://laminatedmaterial.ruhttp://lammasshoot.ruhttp://lamphouse.ruhttp://lancecorporal.ruhttp://lancingdie.ruhttp://landingdoor.ruhttp://landmarksensor.ruhttp://landreform.ruhttp://landuseratio.ruhttp://languagelaboratory.ruhttp://largeheart.ruhttp://lasercalibration.ruhttp://laserlens.ruhttp://laserpulse.ruhttp://laterevent.ruhttp://latrinesergeant.ruhttp://layabout.ruhttp://leadcoating.ruhttp://leadingfirm.ru http://learningcurve.ruhttp://leaveword.ruhttp://machinesensible.ruhttp://magneticequator.ruhttp://magnetotelluricfield.ruhttp://mailinghouse.ruhttp://majorconcern.ruhttp://mammasdarling.ruhttp://managerialstaff.ruhttp://manipulatinghand.ruhttp://manualchoke.ruhttp://medinfobooks.ruhttp://mp3lists.ruhttp://nameresolution.ruhttp://naphtheneseries.ruhttp://narrowmouthed.ruhttp://nationalcensus.ruhttp://naturalfunctor.ruhttp://navelseed.ruhttp://neatplaster.ruhttp://necroticcaries.ruhttp://negativefibration.ruhttp://neighbouringrights.ruhttp://objectmodule.ruhttp://observationballoon.ru http://obstructivepatent.ruhttp://oceanmining.ruhttp://octupolephonon.ruhttp://offlinesystem.ruhttp://offsetholder.ruhttp://olibanumresinoid.ruhttp://onesticket.ruhttp://packedspheres.ruhttp://pagingterminal.ruhttp://palatinebones.ruhttp://palmberry.ruhttp://papercoating.ruhttp://paraconvexgroup.ruhttp://parasolmonoplane.ruhttp://parkingbrake.ruhttp://partfamily.ruhttp://partialmajorant.ruhttp://quadrupleworm.ruhttp://qualitybooster.ruhttp://quasimoney.ruhttp://quenchedspark.ruhttp://quodrecuperet.ruhttp://rabbetledge.ruhttp://radialchaser.ruhttp://radiationestimator.ru http://railwaybridge.ruhttp://randomcoloration.ruhttp://rapidgrowth.ruhttp://rattlesnakemaster.ruhttp://reachthroughregion.ruhttp://readingmagnifier.ruhttp://rearchain.ruhttp://recessioncone.ruhttp://recordedassignment.ruhttp://rectifiersubstation.ruhttp://redemptionvalue.ruhttp://reducingflange.ruhttp://referenceantigen.ruhttp://regeneratedprotein.ruhttp://reinvestmentplan.ruhttp://safedrilling.ruhttp://sagprofile.ruhttp://salestypelease.ruhttp://samplinginterval.ruhttp://satellitehydrology.ruhttp://scarcecommodity.ruhttp://scrapermat.ruhttp://screwingunit.ruhttp://seawaterpump.ruhttp://secondaryblock.ru http://secularclergy.ruhttp://seismicefficiency.ruhttp://selectivediffuser.ruhttp://semiasphalticflux.ruhttp://semifinishmachining.ruhttp://spicetrade.ruhttp://spysale.ruhttp://stungun.ruhttp://tacticaldiameter.ruhttp://tailstockcenter.ruhttp://tamecurve.ruhttp://tapecorrection.ruhttp://tappingchuck.ruhttp://taskreasoning.ruhttp://technicalgrade.ruhttp://telangiectaticlipoma.ruhttp://telescopicdamper.ruhttp://temperateclimate.ruhttp://temperedmeasure.ruhttp://tenementbuilding.rutuchkashttp://ultramaficrock.ruhttp://ultraviolettesting.ru
 
Сверху