Есть ли способ иметь представление для чтения и записи в Range-v3? - PullRequest
0 голосов
/ 20 января 2019

В Range-v3 можно легко создать вид существующих контейнеров. Например

#include<range/v3/view/transform.hpp>
#include<cassert>

int main(){
    std::vector<double> v = {1,2,3};
    auto range = v | ranges::v3::view::transform([](auto x){return x*2;});
    assert( range[1] == 4 );
//    range[1] = 4; // error cannot write to an l-value
}

Эти представления доступны только для чтения. Интересно, есть ли способ создать представление для чтения и записи в Range-v3?

Я действительно ценю, что такая вещь намного сложнее, чем только для чтения, и не всегда возможна, но все же мне интересно, есть ли в Range-v3 протокол для его непосредственного использования или реализации.

Например, я видел примеры производных классов из ranges::view_facade, которые реализуют функцию-член read() (я не могу найти пример снова, документация по Ranges v3 действительно разбросана). А как насчет write(...) функции-члена?

Я ищу гипотетический bi направленный transform код, подобный этому:

#include<range/v3/view/transform.hpp>
#include<cassert>

int main(){
    std::vector<double> v = {1,2,3};
    auto range = v | ranges::v3::view::bitransform([](double x){return x*2;}, [](double x){return x/2;}); // direct and inverse function for read and write
    assert( range[1] == 4 );
    range[1] = 8; // error cannot write to an l-value
    assert( range[1] == 8 );
    assert( v[1] == 4 );
}

1 Ответ

0 голосов
/ 20 января 2019

Вы можете сделать transform_view иметь элементы типа прокси:

#include<vector>
#include<range/v3/view/transform.hpp>
#include<cassert>

struct proxy {
    double& x;
    operator double() { return x*2; }
    void operator=(double y) { x = y / 2; }
};

int main(){
    std::vector<double> v = {1,2,3};
    auto range = v | ranges::v3::view::transform([](auto& x){return proxy{x};});
    assert( range[1] == 4 );
    range[1] = 8;
    assert( range[1] == 8 );
    assert( v[1] == 4 );
}
...