Как реализовать функцию с отложенным вычислением в двух диапазонах C ++ 20? - PullRequest
6 голосов
/ 17 марта 2020

Eri c Niebler предлагает функцию zip_with.

Но теперь, когда в C ++ 20 есть поддержка диапазонов, я хотел бы создать нечто подобное.

Проблема с filter и transform заключается в том, что они повторяют диапазон?

Как бы я go сделал это? Я застрял с этим некоторое время и не хотел бы использовать шаблоны выражений для одного и того же.

Скажем, например, у меня есть два вектора M1 {1,2,3} и M2 {4,5,6 }.

Я хотел бы использовать библиотеку диапазонов, чтобы перегрузить оператор и вернуть представление, которое содержит сложение матрицы этих двух - M1+M2 := {5,7,9}.

С диапазонами-v3 я могу выполнить auto sum = zip_with(std::plus,M1,M2);

Вышеупомянутое выражение оценивается лениво. Как я могу заново создать это выражение в C ++ 20 Ranges?

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Принцип довольно тривиален. Создайте итератор, который хранит итератор для каждого вектора, который при увеличении увеличивает два сохраненных итератора и выполняет сложение только тогда, когда на него делается разыменование.

Вот фрагмент кода, основанный на принципе:

template <class It1, class It2>
struct adder_iterator{
  It1 it1;
  It2 it2;

  decltype(auto)
  operator++(){
    ++it1; ++it2;
    return *this;
    }

  auto
  operator *()const{
    return *it1+*it2;
    }
  //....
  };

Вам также потребуется реализовать сторож и представление (производное от std::view_interface).

Страж - это итератор end. Вы можете использовать класс adder_iterator для этого. Но вы можете подумать об оптимизации: в своем конструкторе представления вы гарантируете, что самый короткий итератор начала вектора всегда равен it1 end, а затем используйте этот итератор только для проверки конца итерации. Вы должны попытаться увидеть.

1 голос
/ 17 марта 2020

Я не знаю, что разрешено в c ++ 20, но следующее работает с пространством имен cpp20 range-v3.

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

int main() {

  std::vector<int> m1 = {1, 2, 3};
  std::vector<int> m2 = {4, 5, 6};

  auto sum = ranges::cpp20::views::transform(m1, m2, std::plus{});

  for (auto i : sum)
      std::cout << i << " "; // 5 7 9
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...