Pull to refresh
94
@izvolovread⁠-⁠only

Декомпозитор

Send message

std::function, Boost.TypeErasure, Boost.Polycollection

Во, вот это правильная реализация.

Как делается настоящее стирание типа без виртуальной шляпы — см. std::function.
Более продвинуто — Boost.TypeErasure.

А за виртуальный метод clone в плюсах полагается расстрел на месте.

Так и не понял, в чём элегантность и "расширяемость" по сравнению, к примеру, с вариантом:

#include <iostream>
#include <variant>

struct circle_t {};
struct square_t {};

struct draw_t
{
    void operator () (const circle_t &) const
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    void operator () (const square_t &) const
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};

int main ()
{
    using shape_t = std::variant<circle_t, square_t>;

    shape_t circle(circle_t{});
    shape_t square(square_t{});

    std::visit(draw_t{}, circle);
    std::visit(draw_t{}, square);
}

Как говорится, нет такого преступления, на которое не пойдут джависты, даже под страхом виселицы, лишь бы обмазаться 300% паттернов.

Программисты на Свифте профильной литературы не читают и в школе институте не учатся?
Зачем обыкновенное О-большое называть "Big O"?

Интересно. Похоже на Boost.TypeErasure.

PI = 3.141597

У вас ус отклеился.


По сути: дико запутанно и неудобно. Непонятно, кто и зачем будет пользоваться этой мешаниной.

Нет, типы знать не нужно. Шаблоном не будет :). Ну то есть будет, но параметры — не итераторы, а тип значения и категория.
Как-то так это можно сделать: https://pastebin.com/Z6wemSjB

Без виртуальных функций можно делать через механизм обобщённых обработчиков. Писал об этом тут: https://habr.com/ru/post/302372/#manager


Или можно посмотреть реализацию std::function в любой современной стандартной библиотеке.

Предварительные результаты замеров в попугаях:
Обычные итераторы: 26
boost::any_iterator: 215
variant_iterator (самописный): 32


Также эксперементирую самописным any_iterator без виртуальных фунций, но быстрее пока не выходит.

Справедливо. Надо бы замерить.

Под множеством, как я говорил, тут подразумевается отсортированный диапазон. Если элементы повторяются, то это "мультимножество".

git clone https://github.com/AlexKiryushkin/rttg
cd rttg/examples
mkdir build && cd build && cmake ..
make

rttg/include/rttg/impl/invoke.h:59:54: error: call to object of type 'rttg::Overloader<(lambda at /Users/izvolov/prog/src/rttg/examples/access_individual_element.cpp:13:18),
      rttg::detail::FallbackEmptyCallable<false> >' is ambiguous
        [&compositeCallable](auto && value) { return compositeCallable(value.get()); },
                                                     ^~~~~~~~~~~~~~~~~

Компилятор clang, макось.

Спасибо!
Сейчас, к сожалению, уже не применяется. Но код открытый, кто знает?..

В данном случае речь идёт о том, что итератор определяет обход последовательности и выдачу элементов.
При этом итератор не знает, что будут делать с выданными им элементами: умножать, складывать, что-то ещё.


Из проблем, навскидку:


  • Неочевидные просадки по производительности в простых случаях (например, если поставить filter после transform, который читает из файла или делает что-то долгое). При этом код корректен, компилируется и работает.
  • Накладные расходы на хранение данных в сложных итераторах (например, чтобы решить предыдущую проблему, можно создать итератор, который будет кэшировать промежуточные вычисления. Но чтобы это засунуть в итератор, потребуется завернуть кэш во что-то типа shared_ptr, а это уже лишний уровень косвенности.

Смотря как сделать :).
Можно сделать сбивающим, но многопозиционным:


const auto result =
    proxima::reduce(items.begin() + 2, items.end() - 3,
        proxima::compose
        (
            drop_nth(3, 5, 19),
            proxima::sum
        ));
1
23 ...

Information

Rating
Does not participate
Registered
Activity