Рассмотрите Как мне написать конвейер диапазона, который использует временные контейнеры?. Вопрос в том, как построить представление, преобразующее каждый элемент T
с помощью некоторой заданной функции.
std::vector<T> f(T t);
соблюдая ограничение (заимствование из верхнего ответа), которое
Представление — это облегченная оболочка, которая представляет представление базовой последовательности элементов каким-то настраиваемым образом, не видоизменяя и не копируя его. Представления недороги в создании и копировании и имеют семантику ссылок без владения.
В принципе, все ответы, похоже, согласны с тем, что из-за этого ограничения это невозможно сделать через представление.
Я не понимаю, как это согласуется с библиотекой, поддерживающей partial_sum
.
Рассмотрим следующее прославленное целое число:
#include <vector>
#include <iostream>
#include <memory>
#include <range/v3/all.hpp>
using namespace ranges;
struct glorified_int {
explicit glorified_int(int i) : m_i{std::make_shared<int>(i)} {}
operator int() const { return *m_i; }
std::shared_ptr<int> m_i;
};
glorified_int operator+(const glorified_int &lhs, const glorified_int &rhs) {
glorified_int ret{(int)lhs + (int)rhs};
return ret;
}
По сути, он просто оборачивает int
в класс, хранящий его в std::shared_ptr
, что позволяет инициализировать, извлекать и добавлять. В.р.т. семантика невладения ссылкой, я не вижу принципиальной разницы между ней и контейнером, таким как std::vector
.
У Range, похоже, нет проблем с применением partial_sum
к этому:
int main() {
std::vector<glorified_int> vi{ glorified_int{1}, glorified_int{2} };
for(const auto &ps: vi | view::partial_sum())
std::cout << ps << std::endl;
Распечатывает
$ ./a.out
1
3
Разве (прославленное целое число) 3 здесь не временно? Это, конечно, не часть оригинальной последовательности. Кроме того, частичная сумма, очевидно, является преобразованием с сохранением состояния, так как диапазон может гарантировать, что
Представления недороги в создании и копировании и имеют семантику ссылок без владения.
Копировать представление так же дорого, как и объект накопления.
Обратите внимание, что также нет проблем с дальнейшим связыванием этого (т. Е. Это не действие):
vi | view::partial_sum() | view::take(10);
Какая тогда разница?
Полный код
#include <vector>
#include <iostream>
#include <memory>
#include <range/v3/all.hpp>
using namespace ranges;
struct glorified_int {
explicit glorified_int(int i) : m_i{std::make_shared<int>(i)} {}
operator int() const { return *m_i; }
std::shared_ptr<int> m_i;
};
glorified_int operator+(const glorified_int &lhs, const glorified_int &rhs) {
glorified_int ret{(int)lhs + (int)rhs};
return ret;
}
int main() {
std::vector<glorified_int> vi{ glorified_int{1}, glorified_int{2} };
for(const auto &ps: vi | view::partial_sum())
std::cout << ps << std::endl;
vi | view::partial_sum() | view::take(10);
}