std::visit
Przetwarzaj alternatywy wariantu
std::visit to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.
Dlaczego std::visit
Ręczne sprawdzanie każdej alternatywy za pomocą get_if szybko staje się rozwlekłe. std::visit stosuje wywoływalny obiekt do typu aktualnie przechowywanego przez wariant i samodzielnie obsługuje wybór właściwej operacji.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 4;
std::visit([](auto x){ std::cout << x << "\n"; }, v);
}Visitor z ogólną lambdą
Lambda przyjmująca auto działa dla każdej alternatywy, jeśli jej ciało kompiluje się dla wszystkich tych typów. W tym przykładzie wypisujemy dowolny aktywny typ.
#include <iostream>
#include <string>
#include <variant>
int main() {
std::variant<int, std::string> v = std::string("hi");
std::visit([](const auto& x){ std::cout << x << "\n"; }, v);
}Zwracanie wartości
std::visit może zwracać wartość. Każda gałąź musi zwracać ten sam typ.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 2.5;
double d = std::visit([](auto x){ return x * 2.0; }, v);
std::cout << d << "\n";
}Zachowanie zależne od typu za pomocą if constexpr
Aby w jednej ogólnej lambdzie wykonywać różne działania zależnie od typu, należy połączyć if constexpr z std::decay_t i std::is_same_v.
#include <iostream>
#include <string>
#include <variant>
#include <type_traits>
int main() {
std::variant<int, std::string> v = 5;
std::visit([](const auto& x){
using T = std::decay_t<decltype(x)>;
if constexpr (std::is_same_v<T, int>) std::cout << "int " << x << "\n";
else std::cout << "str " << x << "\n";
}, v);
}Visitor będący strukturą
Można również napisać strukturę z wieloma przeciążeniami operator(), po jednym dla każdego typu. Kompilator wybierze pasujące przeciążenie.
#include <iostream>
#include <string>
#include <variant>
struct Printer {
void operator()(int i) const { std::cout << "int " << i << "\n"; }
void operator()(const std::string& s) const { std::cout << "str " << s << "\n"; }
};
int main() {
std::variant<int, std::string> v = std::string("yo");
std::visit(Printer{}, v);
}Idiom overloaded
Popularny pomocnik łączy kilka lambd w jeden obiekt visitor. Każda lambda obsługuje konkretny typ.
#include <iostream>
#include <string>
#include <variant>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main() {
std::variant<int, std::string> v = 8;
std::visit(overloaded{
[](int i){ std::cout << "i=" << i << "\n"; },
[](const std::string& s){ std::cout << "s=" << s << "\n"; }
}, v);
}Kompletność obsługi
Visitor musi obsługiwać każdą alternatywę, w przeciwnym razie kod się nie skompiluje. To sprawdzenie na etapie kompilacji zapobiega pominięciu któregoś przypadku.
Odwiedzanie i modyfikowanie
Jeśli przekażesz wariant przez referencję nieconst, visitor będzie mógł modyfikować przechowywaną wartość w miejscu.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 10;
std::visit([](auto& x){ x += 1; }, v);
std::cout << std::get<int>(v) << "\n";
}Wiele wariantów
std::visit może jednocześnie przyjmować kilka wariantów; visitor otrzymuje wtedy po jednym argumencie dla każdego wariantu.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> a = 2;
std::variant<int, double> b = 3.0;
auto sum = std::visit([](auto x, auto y){ return x + y; }, a, b);
std::cout << sum << "\n";
}Wybór stylu visitora
Ogólnej lambdy z auto należy używać do jednolitej obsługi, idiomu overloaded do przejrzystej logiki zależnej od typu, a visitora będącego strukturą wtedy, gdy zachowanie ma być używane ponownie w wielu miejscach wywołania.
Visit a get_if
get_if dobrze sprawdza się przy pojedynczym szybkim sprawdzeniu, ale std::visit lepiej skaluje się w większym kodzie: wymusza kompletną obsługę alternatyw i skupia całą logikę zależną od typu w jednym miejscu.
Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat std::visit.
Podsumowanie
Poznałeś/Poznałaś std::visit:
- Przekazuje wywoływalny obiekt do aktywnej alternatywy.
- Można używać ogólnych lambd,
if constexpr, visitorów będących strukturami lub idiomu overloaded. - Visitery muszą obsługiwać wszystkie alternatywy (jest to sprawdzane podczas kompilacji).
- Mogą zwracać wartości i jednocześnie odwiedzać wiele wariantów.
Często zadawane pytania
Czy lekcja „std::visit” jest bezpłatna?
Tak — pełny tekst „std::visit” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „std::visit”?
Przetwarzaj alternatywy wariantu Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C++ Academy?
Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „std::visit”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?
Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.