Если у вас есть std::variant
с повторяющимися типами, как его назначить? std::variant
по-видимому, допускает дублирование типов.
std::variant<int,int> foo;
компилируется успешно, и все же я не уверен, как назначить foo
, и вдвойне, если я хочу назначить конкретную запись в варианте.
Я пробовал:
std::variant<int,int> foo;
foo = 1;
не удается скомпилировать с ошибкой, что =
не определено для std::variant<int,int>
.
std::variant<int,int> foo;
get<foo, 0> = 1;
не удается скомпилировать с ошибкой, что для определения типа недостаточно информации о контекстном типе.
Я хочу что-то вроде
std::variant<int,int> foo;
something<foo, 1> = 10
assert(foo.index == 1);
assert(get<1>(foo) == 10);
variant::emplace<I>(auto&&...args)
@Джин, это было именно то, что я искал. если бы вы представили это как ответ, я бы принял это.
Это переведет вариант в состояние, в котором 0-я альтернатива активна и ее значение равно 1:
foo.emplace<0>(1);
Обратите внимание, что семантика emplace
в целом не идентична семантике присваивания. Оператор присваивания сначала проверяет, является ли текущая активная альтернатива той же самой, которая должна быть активной после присваивания. Если да, то он просто присваивает существующую альтернативу. Напротив, emplace
всегда сначала уничтожает активную в данный момент альтернативу, а затем создает ее, даже если новая альтернатива имеет тот же индекс, что и старая. Чтобы использовать семантику присваивания, вы должны сделать что-то вроде этого:
if (auto* p = std::get_if<0>(&foo)) {
*p = 1;
} else {
foo.emplace<0>(1);
}
Для целых чисел это не имеет значения, но для более сложных типов присвоение иногда может быть более эффективным, чем уничтожение объекта и создание нового с нужным значением.
связанное/обман: stackoverflow.com/questions/68109028/…