How does range-v3 `partial_sum` not contradict non-referenced semantics?

Consider How to write a range pipeline that uses temporary containers? . The question is how to build a representation that transforms each element Tusing some given function

std::vector<T> f(T t);

observing the restriction (borrowing from the top answer there) that

A view is a lightweight shell, which is a representation of the basic sequence of elements on some ordinary path without modification or copying. Views are cheap to create and copy, and also have inappropriate link semantics.

Basically, all the answers there seem to agree that because of this limitation, this cannot be done with a view.


I don’t understand how this fits into the supporting library partial_sum.

Consider the following distinguished integer:

#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;
}

This basically just ends up intin the class storing it in std::shared_ptr, allowing you to initialize, retrieve, and add. Wrt does not have reference semantics, I do not see a fundamental difference between it and the container, for example std::vector.

The range does not seem to have a problem applying partial_sumto this, though:

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;

Prints out

$ ./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);
}
+4
1

, , , - . , . take() filter() ( , ).

partial_sum . . . - (a optional<glorified_int>) , (a plus). , . , .

:

, .

. . transform() , , , , , , , .

, , , . partial_sum() , , , , partial_sum :

// cheap version
for(const auto &ps: vi | view::partial_sum()) { ... }

// expensive version
std::vector<glorified_int> partial_sums;
if (!vi.empty()) {
    auto it = vi.begin();
    partial_sums.emplace_back(*it++);
    for (; it != vi.end(); ++it) {
        partial_sums.emplace_back(*it + partial_sums.back());
    }
}
for (const auto &ps : partial_sums) { ... }

partial_sums, , ( , , ). , .

+4

Source: https://habr.com/ru/post/1656453/


All Articles