Использование std :: visit в классе, наследующем от std :: variant - libstdc++ vs libС++
Рассмотрим следующий фрагмент кода:
struct v : std::variant<int, std::vector<v>> { };
int main()
{
std::visit([](auto){ }, v{0});
}
живой пример на godbolt.org
Ответы
Ответ 1
[variant.visit] в С++ 17 не использует variant_size_v
, но он работает в текущем рабочем черновике в результате редакционного изменения. Я не вижу никаких указаний на то, что LWG рассмотрел это изменение до того, как оно вступило, но с тех пор он несколько раз смотрел на эту часть стандарта и еще не возражал против этого, поэтому я буду утверждать, что он находится в необходимый факт.
Между тем, проблема 305 LWG, которая была передана LEWG, явно потребовала бы std::variant
. Когда эта проблема решена - так или иначе - она также должна решить эту проблему.
Ответ 2
Похоже, что это ошибка в gcc-реализации. Согласно cppreference, это называется, как будто призывая invoke
на std::get
. std::get<>
определяется для всего, что конвертируется в std::variant
(поскольку он принимает аргумент std::variant
посредством ссылки пересылки). Ваша структура конвертируется в std::variant
, и поэтому std::get
сам работает над вашей структурой в gcc.
Тот факт, что реализация gcc решила использовать std::variant_size
качестве части его реализации visit
является их детальность реализации, а тот факт, что она не работает (и не должна) для вашей структуры, не имеет значения.
Вывод: это ошибка в gcc из-за надзора в реализации.