Pull to refresh

Comments 5

Спасибо за статью. Интересно.
Не совсем понятен вопрос, в чём преимущество перед диапазонами? Вы сами про них упоминаете, но в чём их минусы? Почему бы не пользоваться ими?
Там компонуемость лучше, написание функций проще и без макросов. Тот же пример из документации:
std::vector<int> vi{1,2,3,4,5,6,7,8,9,10};
using namespace ranges;
auto rng = vi | view::remove_if([](int i){return i % 2 == 1;})
              | view::transform([](int i){return std::to_string(i);});
// rng == {"2","4","6","8","10"};

Ничто не мешает пользоваться ими уже сейчас. Да, не в std, но ranges-v3 уже работающая header-only имплементация. Принести её в проект ничего не стоит.

Спасибо за вопрос. Во вступлении я об этом упоминал, но не слишком подробно.


Я ни в коем случае не утверждаю, что есть какие-то преимущества перед диапазонами. Наоборот, всё, что здесь описано, как раз и родилось из активного использования диапазонов и адаптеров.


// Полупсевдокод

struct Class
{
    std::string name;
    std::size_t index;
};

std::vector<Class> v{...};
const auto r =
    ranges::view::zip(v, ranges::view::iota(0ul))
        | ranges::view::transform(make_from_tuple<Class>)
        | ranges::to_vector
        | ranges::action::sort(each(MEMBER(name)) | std::greater<>{});

В данной публикации я хотел описать именно технику. А поскольку техника сама по себе не требует работы именно с диапазонам, то, чтобы не вводить новых сущностей, я пользовался исключительно стандартной библиотекой.

Интересная статья, спасибо за труд. Объясните пожалуйста, зачем вы здесь вызываете std::move?


template <typename ... Ts>
constexpr decltype(auto) operator () (Ts && ... ts) &&
{
    return std::move(l)(std::move(r)(std::forward<Ts>(ts)...));
}

С удовольствием.


Факт №1


Методы классов в языке C++ могут перегружаться по категории экземпляра класса:


struct Class
{
    void f () const &; // Вызывается, когда экземпляр является ссылкой на константу.
    void f () &; // Вызывается, когда экземпляр является ссылкой.
    void f () &&; // Вызывается, когда экземпляр является ссылкой на rvalue.
};

https://wandbox.org/permlink/Og3kWTDeZFMj0ncP


Факт №2


Функциональный объект может быть классом, обладающим нетривиальным состоянием и имеющим перегрузки оператора "скобки", описанные выше.


Суть


Теперь реализуем такой функциональный объект с состоянием и перегрузками оператора вызова.


Пусть это будет функциональный объект, который хранит некоторую строчку, в оператор вызова принимает контейнер, в который он эту строчку записывает:


template <typename T>
struct push_back_fn
{
    T value;

    template <typename Container>
    void operator () (Container & c) const &
    {
        c.push_back(value);
    }

    template <typename Container>
    void operator () (Container & c) &
    {
        c.push_back(value);
    }

    template <typename Container>
    void operator () (Container & c) &&
    {
        // Наш объект является `rvalue`, а значит, скоро закочит своё
        // существование. Следовательно, строчка ему больше не понадобится,
        // так что владение строчкой можно отдать контейнеру.

        c.push_back(std::move(value)); // <--
    }
};

template <typename T>
auto push_back (T && t)
    -> push_back_fn<std::decay_t<T>>
{
    return {std::forward<T>(t)};
}

Теперь использование:


int main ()
{
    // Сохранили экземпляр нашего функционального объекта. Он `lvalue`.
    auto pb = push_back(std::string("qwerty"));

    // Записали копию строки в конец контейнера.
    std::vector<std::string> v;
    pb(v);

    // Записали ещё одну копию той же строки в коней другого контейнера.
    std::vector<std::string> w;
    pb(w);

    // А здесь наш `push_back_fn` вызывается как `rvalue`,
    // поэтому ни одного копирования не произошло.
    push_back(std::string("asdfgh"))(v);
}

https://wandbox.org/permlink/MK2gIPzT3TOWBlw5


Исходя из всего вышеперечисленного, при композиции нужно обеспечить правильные вызовы каждого функционального объекта, чтобы не производить лишние действия в том случае, когда этого можно избежать.

Спасибо, теперь понял. Смутило, что в примерах в статье отсутствуют эти перегрузки.

Sign up to leave a comment.

Articles