C++ std: dowolne przykłady

C Std Dowolne Przyklady



W programowaniu w C++ polecenie „std::any” ze standardowej biblioteki szablonów (STL) wprowadza dynamiczne pisanie w celu obsługi heterogenicznych danych. W przeciwieństwie do tradycyjnych kontenerów, „std::any” umożliwia przechowywanie wartości dowolnego typu w jednym kontenerze, zwiększając elastyczność w scenariuszach, w których typy danych są nieznane lub zmieniają się w czasie wykonywania. To podejście niezależne od typu promuje programowanie generyczne, które umożliwia programistom tworzenie bardziej elastycznego i wyrazistego kodu przy jednoczesnym zachowaniu bezpieczeństwa typu. W tej eksploracji zagłębimy się w funkcje „std::any”, jego wzorce użycia i praktyczne przykłady ilustrujące jego rolę w pisaniu solidnego i elastycznego kodu C++.

Przykład 1: Podstawowe użycie Std::Any

Najpierw przeanalizujmy prosty przykład, aby zademonstrować podstawowe użycie „std::any”. Rozważmy scenariusz, w którym potrzebujesz funkcji akceptowającej różne typy parametrów:







Oto fragment kodu:



#include
#uwzględnij

unieważniony procesDowolny ( stała std::dowolna & wartość ) {
Jeśli ( wartość.ma wartość_ ( ) ) {
std::cout << „Typ przechowywanej wartości: „ << typ wartości ( ) .nazwa ( ) << std::endl;

Jeśli ( typ wartości ( ) == wpisz ( wew ) ) {
std::cout << 'Wartość: ' << std::any_cast < wew > ( wartość ) << std::endl;
} w przeciwnym razie Jeśli ( typ wartości ( ) == wpisz ( podwójnie ) ) {
std::cout << 'Wartość: ' << std::any_cast < podwójnie > ( wartość ) << std::endl;
} w przeciwnym razie Jeśli ( typ wartości ( ) == wpisz ( std::string ) ) {
std::cout << 'Wartość: ' << std::any_cast < std::string > ( wartość ) << std::endl;
} w przeciwnym razie {
std::cout << „Nieobsługiwany typ!” << std::endl;
}
} w przeciwnym razie {
std::cout << „Brak wartości zapisanej w std::any.” << std::endl;
}
}

int główny ( ) {
procesDowolny ( 42 ) ;
procesDowolny ( 3.14 ) ;
procesDowolny ( std::string ( „Witam, std::any!” ) ) ;
procesDowolny ( 4,5 f ) ; // Nieobsługiwane typ

powrót 0 ;
}


W tym przykładzie definiujemy funkcję „processAny”, która przyjmuje odwołanie „std::any” jako parametr i sprawdza jego zawartość. Wewnątrz funkcji najpierw sprawdzamy, czy zmienna „std::any” ma zapisaną wartość, używając funkcji has_value(). Jeśli wartość jest obecna, określamy typ przechowywanej wartości za pomocą type().name() i przystępujemy do drukowania odpowiedniej wartości w oparciu o jej typ. Następnie główna funkcja demonstruje użyteczność „processAny”, wywołując ją z różnymi typami: liczbą całkowitą (42), wartością podwójną (3.14) i ciągiem („Hello, std::any!”). Funkcja odpowiednio obsługuje każdy typ i wypisuje odpowiednie wartości. Jednak podczas próby przetworzenia liczby zmiennoprzecinkowej (4.5f), która nie jest obsługiwana w tym przykładzie, program sprawnie radzi sobie z sytuacją, wskazując, że typ nie jest obsługiwany.



Wygenerowane dane wyjściowe to:






To pokazuje, jak „std::any” umożliwia dynamiczną obsługę różnych typów danych, co czyni go wszechstronnym narzędziem do programowania ogólnego w C++.

Przykład 2: Przechowywanie typów zdefiniowanych przez użytkownika

Drugi przykład bada, w jaki sposób ten dynamiczny typ w standardowej bibliotece szablonów (STL) bezproblemowo dostosowuje niestandardowe struktury danych. Koncentrując się na typie zdefiniowanym przez użytkownika, strukturze punktowej, pokazujemy, jak „std::any” obsługuje wystąpienia takich struktur.



Oto kod:

#include
#uwzględnij

klasa MojaKlasa {
publiczny:
Moja klasa ( wartość całkowita ) : dane ( wartość ) { }

unieważnij dane wydruku ( ) konst {
std::cout << „Dane w MyClass:” << dane << std::endl;
}

prywatny:
dane int;
} ;

int główny ( ) {
std::any anyObject = MojaKlasa ( 42 ) ;

Jeśli ( anyObject.has_value ( ) ) {
automatyczny & myClassInstance = std::any_cast < Moja klasa &> ( dowolny obiekt ) ;
myClassInstance.printData ( ) ;
} w przeciwnym razie {
std::cout << „Brak wartości zapisanej w std::any.” << std::endl;
}

powrót 0 ;
}


W tym fragmencie kodu C++ tworzymy prosty przykład ilustrujący użycie typu „std::any” ze zdefiniowaną przez użytkownika klasą o nazwie „MyClass”. Wewnątrz klasy znajduje się prywatna zmienna składowa o nazwie „data” oraz metoda publiczna o nazwie printData(), która wyświetla wartość tych danych. Wartość całkowita jest przekazywana i przypisywana do elementu „data” w konstruktorze.

W funkcji „main” tworzymy instancję obiektu „MyClass” o wartości początkowej 42, a następnie przechowujemy go w zmiennej „std::any” o nazwie „anyObject”. To pokazuje, że „std::any” może przechowywać instancje klas zdefiniowanych przez użytkownika.

Następnie używamy instrukcji „if”, aby sprawdzić, czy „anyObject” ma wartość, za pomocą metody has_value(). Jeśli istnieje wartość, pobieramy przechowywany obiekt za pomocą „std::any_cast”. Parametr „std::any_cast” jest używany z argumentem szablonu „MojaKlasa&”, aby rzutować przechowywany obiekt na odwołanie do „MojejKlasy”. To odwołanie „myClassInstance” jest następnie używane do wywołania metody printData(), prezentując możliwość dostępu i operowania na przechowywanym typie zdefiniowanym przez użytkownika w ramach „std::any”.

Jeśli w „std::any” nie jest zapisana żadna wartość, wypisujemy komunikat o tym. To sprawdzenie warunkowe gwarantuje, że poradzimy sobie ze scenariuszami, w których zmienna „std::any” może być pusta.

Oto dane wyjściowe:

Przykład 3: Kontener typów mieszanych

W programowaniu „kontener typu mieszanego” odnosi się do struktury danych, która jest w stanie przechowywać elementy różnych, potencjalnie niepowiązanych typów danych. Ta elastyczność jest cenna w przypadku scenariuszy, w których typy danych są nieznane w czasie kompilacji lub dynamicznie zmieniają się podczas wykonywania programu. W C++ „std::any” jest przykładem tej koncepcji, umożliwiając utworzenie pojedynczego kontenera do przechowywania wartości różnych typów.

Przyjrzyjmy się scenariuszowi, w którym tworzymy kontener zawierający różne typy:

#include
#uwzględnij
#uwzględnij

int główny ( ) {

std::wektor < std::dowolny > mieszanyPojemnik;

mieszanyContainer.push_back ( 42 ) ;
mieszanyContainer.push_back ( 3.14 ) ;
mieszanyContainer.push_back ( std::string ( 'Cześć' ) ) ;
mieszanyContainer.push_back ( PRAWDA ) ;

Do ( stała auto & element: mieszany kontener ) {
Jeśli ( typ.elementu ( ) == wpisz ( wew ) ) {
std::cout << „Liczba całkowita:” << std::any_cast < wew > ( element ) << std::endl;
} w przeciwnym razie Jeśli ( typ.elementu ( ) == wpisz ( podwójnie ) ) {
std::cout << „Podwójne:” << std::any_cast < podwójnie > ( element ) << std::endl;
} w przeciwnym razie Jeśli ( typ.elementu ( ) == wpisz ( std::string ) ) {
std::cout << 'Strunowy: ' << std::any_cast < std::string > ( element ) << std::endl;
} w przeciwnym razie Jeśli ( typ.elementu ( ) == wpisz ( bool ) ) {
std::cout << „Boole:” << std::any_cast < bool > ( element ) << std::endl;
} w przeciwnym razie {
std::cout << „Nieznany typ” << std::endl;
}
}

powrót 0 ;
}


Na tej ilustracji przedstawiamy koncepcję kontenera typu mieszanego przy użyciu języka C++ i funkcji „std::any”. Tworzymy „std::vector” o nazwie „mixedContainer”, który będzie służył jako nasz kontener do przechowywania elementów różnych typów danych. Używając funkcji „push_back”, wypełniamy ten kontener różnymi elementami, w tym liczbą całkowitą (42), wartością podwójną (3.14), ciągiem znaków („Hello”) i wartością logiczną (true).

Podczas iteracji po „mixedContainer” za pomocą pętli „for” używamy funkcji type() do dynamicznej identyfikacji typu danych każdego elementu. Wykorzystując „std::any_cast” wyodrębniamy i drukujemy odpowiednie wartości w oparciu o ich typy. Na przykład, jeśli element jest typu „int”, wypisujemy go jako liczbę całkowitą. Jeśli jest typu „double”, drukujemy go jako double i tak dalej.

Oto wygenerowany wynik:

Przykład 4: Obsługa błędów za pomocą Std::Any

Obsługa błędów podczas korzystania z „std::any” polega na sprawdzeniu, czy typ jest obsługiwany i czy wartość jest przechowywana. W tym przykładzie pokazujemy, jak obsługiwać nieobsługiwane typy:

#include
#uwzględnij

int główny ( ) {
std::any myAny = 42 ;

próbować {

podwójna wartość = std::any_cast < podwójnie > ( mójAny ) ;
std::cout << 'Wartość: ' << wartość << std::endl;
} złapać ( const std::bad_any_cast & To jest ) {

std::cerr << 'Błąd: ' << e. co ( ) << std::endl;
}

powrót 0 ;
}


Zaczynamy od inicjalizacji zmiennej „std::any” „myAny” wartością 42 typu całkowitego. W kolejnym bloku „try” podejmujemy jawną próbę rzutowania tej wartości całkowitej na „double” za pomocą operacji „std::any_cast”. Ponieważ jednak rzeczywisty typ przechowywany w „myAny” jest liczbą całkowitą, ta operacja rzutowania jest nieprawidłowa w przypadku „double”, co prowadzi do niedopasowania typu.

Aby sprawnie zarządzać tym potencjalnym błędem, implementujemy obsługę wyjątków za pomocą bloku „catch”, który ma za zadanie przechwytywać konkretny typ wyjątku „std::bad_any_cast”. W przypadku niepowodzenia rzutowania aktywowany jest blok „catch”, a my generujemy komunikat o błędzie za pomocą „std::cerr”, aby poinformować o naturze błędu. Ta strategia obsługi błędów gwarantuje, że nasz program będzie w stanie z łatwością poradzić sobie z sytuacjami, w których próba rzutowania typu koliduje z rzeczywistym typem przechowywanym w zmiennej „std::any”.

Wniosek

W tym artykule zbadaliśmy zastosowania „std::any” w C++, kontenerze typu dynamicznego, który został wprowadzony w C++ dla wartości różnych typów. Zademonstrowaliśmy jego wszechstronność na różnych przykładach, prezentując scenariusze obejmujące zakres od podstawowego użycia po obsługę typów zdefiniowanych przez użytkownika i heterogenicznych kolekcji. Zademonstrowaliśmy jego praktyczne zastosowanie w scenariuszach, w których typ danych nie jest znany w czasie kompilacji. Dodatkowo zbadaliśmy techniki obsługi błędów, podkreślając znaczenie płynnego zarządzania nieobsługiwanymi typami poprzez obsługę wyjątków.