ideas
ideas copied to clipboard
Недостающий инструмент динамического полиморфизма в стандарте
Мотивация частично описана тут: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0957r6.pdf И тут : https://github.com/kelbon/AnyAny Если очень кратко - текущие инструменты динамического полиморфизма недостаточны : виртуальные функции и код, который с ними получается, не отражает реальных намерений программиста (бесконечные поинтеры, управление памятью, наследование и проч.), std::any практически бесполезен (единственная его польза это деструктор, то есть гарантия что что-то удалится). std::variant уже гораздо лучше, но неудобен в использовании, плохо расширяем(если добавляется новый тип приходится менять все места его использования), когда типов много визиторы в реальном коде становятся громадными, большие проблемы с исключениями(valueless_by_exception), а если написать std::visit с двумя визиторами можно раздуть бинарник до гигабайтов(что мягко говоря неочевидно для новичков да и опытных...)
Моё предложение заполняет нишу, где variant плох, а виртуальные функции ужасны. Там, где реально нужен полиморфный объект
Представим что нужен класс машины, где есть двигатель и его можно менять на рантайме. Кажется наилучшее выражение мысли в коде это
struct Machine {
any_engine engine_;
};
И с моим предложением реализация выглядит так:
template<typename T>
struct Go {
static int do_invoke(T self, int value) {
self.Go(value);
return value * 4;
}
}
using any_engine = any_with<Go>; // здесь может передаваться произвольное количество методов
Вызывать методы можно либо через invoke<Go>(engine); либо написав в классе метод (и тогда будет выглядеть как обычный класс), см. реализацию и readme. На мой личный взгляд интерфейс гораздо удобнее чем у предлагаемого std::proxy, при этом у меня есть строгая гарантия исключений(которой нет в std::proxy) и value семантика, реализация судя по бенчмаркам практически такая же по производительности как и variant Аллокатор и размер SOO буфера регулируемы, можно добавлять любое количество методов, реализовывать передачу self по копии(кстати выше в примере с машиной так и происходит) и многое другое
Реализация тут:
https://github.com/kelbon/AnyAny