Чем больше вещей вы проверяете во время компиляции, тем меньше у вас ошибок времени выполнения.
variant
гарантирует, что он содержит один из списка типов (плюс бесполезный за исключением). Это дает вам возможность гарантировать, что работающий на нем код учитывает каждый случай в варианте с std::visit
; даже каждый случай для пары из variant
с (или более).
any
нет. С any
лучшее, что вы можете сделать, это «если тип не совсем то, что я запрашиваю, некоторый код не будет работать».
variant
существует в автоматическом хранилище. any
может использовать бесплатный магазин; это означает, что any
имеет производительность, а noexcept(false)
- проблемы, которые variant
не имеет.
Проверка, для какого из N типов он есть, составляет O (N), для any
- для variant
это O (1).
any
это наряд void*
. variant
это наряд union
.
any
не может хранить типы, не предназначенные для копирования или перемещения. variant
банка.
Тип variant
- документация для читателя вашего кода.
Передача variant<Msg1, Msg2, Msg3>
через API делает операцию очевидной; пропуск any
означает, что понимание API требует надежной документации или чтения источника реализации.
Любой, кто был разочарован статически не типизированными языками, поймет опасность any
.
Теперь это не значит, что any
- это плохо; это просто не решает те же проблемы, что и variant
. Как копируемый объект для стирания типа, он может быть великолепным. Динамическая типизация во время выполнения имеет свое место; но это место не «везде», а «где вы не можете избежать его».