Odczytywanie informacji z variant

0

Załóżmy, że mam taki wektor:

std::vector<std::variant<std::string, char, bool, int, float, double> > variantVector;

do którego dodaję, a następnie odczytuję dane:

variantVector[0].emplace<int>(12345);
variantVector[0].emplace<std::string>("text");

std::cout << std::get<std::string>(variantVector[0]);

W tym wypadku wyświetlony zostaje "text". Gdybym "dodał" do variantVector[0] najpierw std::string, a później int, wyrzucony zostanie błąd. W jaki sposób mogę odczytać wszystkie wartości zmiennych w variantVector[0], a nie tylko tą ostatnią?

Mam też pytanie dotyczące typów w std::variant - czy można stworzyć taki variant, który zaakceptuje każdy typ, nieuwzględniony wcześniej w definicji (na zasadzie auto lub std::any)?

2

variant to unia z tagiem. Główną charakterystyką unii/variantu jest właśnie to, że trzyma jeden z elementów na raz.

Może to słaba analogia, ale pomyśl o variancie jak o toalecie. Na raz do środka wchodzi jedna osoba. Jak wchodzi nowa, to stara jest usuwana, więc kiedykolwiek sprawdzisz, będzie tam tylko ostatnia osoba która weszła.

0

@kq: Jakie zastosowanie ma w takim razie index()? I co się dzieje ze "starą" wartością?

1

Informuje która jest obecnie w użyciu. Jest usuwana.

0

Rozumiem. Czy w takim razie variant może przyjmować każdy typ (drugie pytanie)? Czy liczba indeksów musi być znana przy definicji variantu?

1

variant może przyjąć każdy typ jaki został zdefiniowany dla danego variantu. Definicja musi być znana w czasie kompilacji. Trick answer może dorzucić std::any, które przyjmuje dowolny typ.

0

Kod z std::vector< variant<any> > się nie kompiluje - występują takie błędy jak std::variantstd::any::emplace': no matching overloaded function found i takie, informujące, że nie można porównywać takich variantów (x.vectorVariant == y.vectorVariant).

1

Może lepiej opisz co chcesz zrobić, bo w tej chwili rzucasz się bezmyślnie na każde hasło jakie usłyszysz.
Sama kombinacja variant<any> dowodzi, że nie masz pojęcia co chcesz zrobić.

0

Chciałbym, żeby variant przyjmował np. każdy typ is_integral.

1

a nie prościej po prostu posługiwać się najbardziej pojemnym typem całkowitym?
Czemu się upierasz przy variant? Co chcesz tym zyskać?
Najlepiej opisz problem który próbujesz rozwiązać za pomocą variant!

Wygląda na to, że źle zadajesz pytanie. Takie zadawanie pytania jest to opisane jako problem XY.

1
#include <iostream>

#include <type_traits>
#include <variant>
#include <vector>

struct Visitor
{
    void operator()(int const& v) { std::cout << "int const& " << v << "\n"; }
    void operator()(std::string const& v) { std::cout << "std::string const& " << v << "\n"; }
    void operator()(double const& v) { std::cout << "double const& " << v << "\n"; }
    void operator()(long const& v) { std::cout << "long const& " << v << "\n"; }
};

int main()
{
    using variant = std::variant<std::string, int, double, long>;
    std::vector<variant> vec {
        7,
        "Text",
        3.5,
        "Hello",
        -5l
    };
    
    for(auto& e : vec) {
        std::visit(Visitor(), e);
    }

    return 0;
}

https://wandbox.org/permlink/r6VoGy5tXFrv32BM

0

W zależności od wyboru użytkownika wartości mają być std::string lub is_integral (a więc nie chodzi o pojemność). Udało mi się z emplace: variantVector.emplace<any>(make_any<string>("text")), nie wiem jednak, jak to porównywać.

1

Nadal masz problem XY. Zamiast mówić nam jak chcesz problem rozwiązać szalonymi pomysłami, powiedz jaki masz problem.

0

Nie wiem jak porównywać wektor variantstd::any.

0

A po co chcesz go porównywać?

0

Zacznij tak:

Jako użytkownik końcowy, chcę wpisać X, a jako rezultatu oczekuję Y.

0
kq napisał(a):

A po co chcesz go porównywać?

Wektor jest częścią klasy (niezwiązanej z tym problemem), która ma przeładowany operator==.

0

Przeniosłem wektor do osobnej klasy z operatorem i porównanie działa. Dziękuję za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1