Интерфейс и все свойства и гарантии должны соответствовать std::variant. Специализацию std::hash
писать не надо.
По аналогии с заданием optional, требуется по возможности сохранять тривиальности для special members (деструктора, конструкторов и операторов присваивания). Также стоит уделить внимание правильности расставления noexcept
.
Обратите внимание на описание на cppreference для converting конструктора/operator=, которое прямо говорит, как их реализовывать. Такой код должен работать ожидаемым образом:
variant<string, bool> x = "abc"; // holds string
Но проблема в том, что указатель char const*
приводится как к bool
, так и к string
. Изначально для этого в стандарте сделали небольшой "костыль" в P0608R3, по сути обработав специально ситуацию с конвертацией к bool (см. статью). Это иногда ведёт себя неожиданным образом, но пример выше благодаря такому работает.
Потом конверсию к bool признали narrowing: P1957R2, а такие конвертации запрещены в константных выражениях. В том же предложении убрали "костыль" для конструктора варианта: теперь то, что отсекалось им, должно отсекаться из-за narrowing conversion и он больше не нужен.
Но так случилось, что в имплементациях стандартной библиотеки реализовали изменение variant, но narrowing conversion сам реализовали только в свежих версиях компиляторах компиляторах, которых может не быть у вас локально. В результате реализовать без "костыля" правильное поведение на условном gcc-10 сейчас не получится, поэтому предлагается осознать всё выше написанное и имплементировать поведение из P0608R3. Если вы хотите понять ещё больше, то рекомендуется попробовать воспроизвести минимальные примеры с разными типами variant в godbolt.org на разных версиях компиляторов.