C++ std:any Beispiele

C Std Any Beispiele



In der C++-Programmierung führt „std::any“ aus der Standard Template Library (STL) eine dynamische Typisierung ein, um heterogene Daten zu verarbeiten. Im Gegensatz zu herkömmlichen Containern ermöglicht „std::any“ das Speichern von Werten jeden Typs in einem einzigen Container und erhöht so die Flexibilität in Szenarien, in denen die Datentypen unbekannt sind oder zur Laufzeit variieren. Dieser typunabhängige Ansatz fördert eine generische Programmierung, die es den Entwicklern ermöglicht, einen anpassungsfähigeren und aussagekräftigeren Code zu erstellen und gleichzeitig die Typsicherheit aufrechtzuerhalten. In dieser Untersuchung befassen wir uns mit den Funktionen von „std::any“, seinen Verwendungsmustern und praktischen Beispielen, die seine Rolle beim Schreiben eines robusten und flexiblen C++-Codes veranschaulichen.

Beispiel 1: Grundlegende Verwendung von Std::Any

Lassen Sie uns zunächst ein einfaches Beispiel untersuchen, um die grundlegende Verwendung von „std::any“ zu demonstrieren. Stellen Sie sich ein Szenario vor, in dem Sie eine Funktion benötigen, die verschiedene Parametertypen akzeptiert:







Hier ist der Codeausschnitt:



#include
#include

ungültiger ProzessAny ( const std::any & Wert ) {
Wenn ( value.has_value ( ) ) {
std::cout << „Typ des gespeicherten Werts:“ << Werttyp ( ) .Name ( ) << std::endl;

Wenn ( Werttyp ( ) == Typ-ID ( int ) ) {
std::cout << 'Wert: ' << std::any_cast < int > ( Wert ) << std::endl;
} anders Wenn ( Werttyp ( ) == Typ-ID ( doppelt ) ) {
std::cout << 'Wert: ' << std::any_cast < doppelt > ( Wert ) << std::endl;
} anders Wenn ( Werttyp ( ) == Typ-ID ( std::string ) ) {
std::cout << 'Wert: ' << std::any_cast < std::string > ( Wert ) << std::endl;
} anders {
std::cout << „Nicht unterstützter Typ!“ << std::endl;
}
} anders {
std::cout << „Kein Wert in std::any gespeichert.“ << std::endl;
}
}

int main ( ) {
ProzessAny ( 42 ) ;
ProzessAny ( 3.14 ) ;
ProzessAny ( std::string ( „Hallo, std::any!“ ) ) ;
ProzessAny ( 4,5f ) ; // Nicht unterstützt Typ

zurückkehren 0 ;
}


In diesem Beispiel definieren wir die Funktion „processAny“, die eine „std::any“-Referenz als Parameter verwendet und deren Inhalt untersucht. Innerhalb der Funktion prüfen wir zunächst mit has_value(), ob die Variable „std::any“ einen gespeicherten Wert hat. Wenn ein Wert vorhanden ist, ermitteln wir mit type().name() den Typ des gespeicherten Werts und drucken den entsprechenden Wert basierend auf seinem Typ aus. Die Hauptfunktion demonstriert dann die Nützlichkeit von „processAny“, indem sie sie mit verschiedenen Typen aufruft: einer Ganzzahl (42), einem Double (3.14) und einem String („Hallo, std::any!“). Die Funktion verarbeitet jeden Typ entsprechend und gibt die entsprechenden Werte aus. Beim Versuch, eine Gleitkommazahl (4.5f) zu verarbeiten, die in diesem Beispiel nicht unterstützt wird, geht das Programm jedoch elegant mit der Situation um, indem es anzeigt, dass der Typ nicht unterstützt wird.



Die generierte Ausgabe ist:






Dies zeigt, wie „std::any“ die dynamische Handhabung verschiedener Datentypen ermöglicht und es zu einem vielseitigen Werkzeug für die generische Programmierung in C++ macht.

Beispiel 2: Speichern der benutzerdefinierten Typen

Im zweiten Beispiel wird untersucht, wie dieser dynamische Typ innerhalb der Standard Template Library (STL) die benutzerdefinierten Datenstrukturen nahtlos unterstützt. Wir konzentrieren uns auf einen benutzerdefinierten Typ, die Punktstruktur, und zeigen, wie „std::any“ mit den Instanzen solcher Strukturen umgeht.



Hier ist der Code:

#include
#include

Klasse MyClass {
öffentlich:
Meine Klasse ( int-Wert ) : Daten ( Wert ) { }

void printData ( ) const {
std::cout << „Daten in MyClass:“ << Daten << std::endl;
}

Privat:
int-Daten;
} ;

int main ( ) {
std::any anyObject = MyClass ( 42 ) ;

Wenn ( anyObject.has_value ( ) ) {
Auto & myClassInstance = std::any_cast < Meine Klasse &> ( irgendeinObjekt ) ;
myClassInstance.printData ( ) ;
} anders {
std::cout << „Kein Wert in std::any gespeichert.“ << std::endl;
}

zurückkehren 0 ;
}


In diesem C++-Codeausschnitt erstellen wir ein einfaches Beispiel, um die Verwendung des Typs „std::any“ mit einer benutzerdefinierten Klasse namens „MyClass“ zu veranschaulichen. Innerhalb der Klasse gibt es eine private Mitgliedsvariable namens „data“ und eine öffentliche Methode namens printData(), um den Wert dieser Daten anzuzeigen. Ein ganzzahliger Wert wird übergeben und dem „data“-Member im Konstruktor zugewiesen.

In der „main“-Funktion instanziieren wir ein Objekt von „MyClass“ mit einem Anfangswert von 42 und speichern es dann in der „std::any“-Variable mit dem Namen „anyObject“. Dies demonstriert die Fähigkeit von „std::any“, die Instanzen benutzerdefinierter Klassen zu speichern.

Anschließend überprüfen wir mithilfe einer „if“-Anweisung mithilfe der Methode has_value(), ob „anyObject“ einen Wert hat. Wenn ein Wert vorhanden ist, rufen wir das gespeicherte Objekt mit „std::any_cast“ ab. „std::any_cast“ wird mit dem Vorlagenargument „MyClass&“ verwendet, um das gespeicherte Objekt in eine Referenz von „MyClass“ umzuwandeln. Diese Referenz „myClassInstance“ wird dann zum Aufrufen der printData()-Methode verwendet und zeigt die Möglichkeit, auf den gespeicherten benutzerdefinierten Typ innerhalb von „std::any“ zuzugreifen und ihn zu bearbeiten.

Wenn in „std::any“ kein Wert gespeichert ist, geben wir eine entsprechende Meldung aus. Diese bedingte Prüfung stellt sicher, dass wir die Szenarien behandeln, in denen die Variable „std::any“ möglicherweise leer ist.

Hier ist die Ausgabe:

Beispiel 3: Container mit gemischten Typen

In der Programmierung bezieht sich ein „Mixed-Type-Container“ auf eine Datenstruktur, die die Elemente verschiedener, möglicherweise nicht verwandter Datentypen enthalten kann. Diese Flexibilität ist wertvoll, wenn es um Szenarien geht, bei denen die Datentypen zur Kompilierungszeit unbekannt sind oder sich während der Programmausführung dynamisch ändern. In C++ veranschaulicht „std::any“ dieses Konzept und ermöglicht die Erstellung eines einzelnen Containers zum Speichern der Werte verschiedener Typen.

Sehen wir uns ein Szenario an, in dem wir einen Container erstellen, der verschiedene Typen enthält:

#include
#include
#include

int main ( ) {

std::vector < std::any > gemischtContainer;

MixedContainer.push_back ( 42 ) ;
MixedContainer.push_back ( 3.14 ) ;
MixedContainer.push_back ( std::string ( 'Hallo' ) ) ;
MixedContainer.push_back ( WAHR ) ;

für ( const auto & Element: MixedContainer ) {
Wenn ( element.type ( ) == Typ-ID ( int ) ) {
std::cout << „Ganzzahl:“ << std::any_cast < int > ( Element ) << std::endl;
} anders Wenn ( element.type ( ) == Typ-ID ( doppelt ) ) {
std::cout << 'Doppelt: ' << std::any_cast < doppelt > ( Element ) << std::endl;
} anders Wenn ( element.type ( ) == Typ-ID ( std::string ) ) {
std::cout << „Zeichenfolge:“ << std::any_cast < std::string > ( Element ) << std::endl;
} anders Wenn ( element.type ( ) == Typ-ID ( bool ) ) {
std::cout << „Boolean:“ << std::any_cast < bool > ( Element ) << std::endl;
} anders {
std::cout << „Unbekannter Typ“ << std::endl;
}
}

zurückkehren 0 ;
}


In dieser Abbildung demonstrieren wir das Konzept eines gemischten Containers mit C++ und der Funktion „std::any“. Wir erstellen den „std::vector“ mit dem Namen „mixedContainer“, der als Container für die Elemente verschiedener Datentypen dient. Mit der Funktion „push_back“ füllen wir diesen Container mit verschiedenen Elementen, darunter einer Ganzzahl (42), einem Double (3.14), einem String („Hello“) und einem Booleschen Wert (true).

Während wir den „mixedContainer“ mithilfe einer „for“-Schleife durchlaufen, verwenden wir die Funktion type(), um den Datentyp jedes Elements dynamisch zu identifizieren. Mithilfe von „std::any_cast“ extrahieren und drucken wir die entsprechenden Werte basierend auf ihren Typen. Wenn das Element beispielsweise vom Typ „int“ ist, geben wir es als Ganzzahl aus. Wenn es vom Typ „double“ ist, drucken wir es als double und so weiter.

Hier ist die generierte Ausgabe:

Beispiel 4: Fehlerbehandlung mit Std::Any

Zur Behandlung von Fehlern bei der Verwendung von „std::any“ gehört die Prüfung, ob der Typ unterstützt wird oder ob ein Wert gespeichert ist. In diesem Beispiel zeigen wir, wie mit den nicht unterstützten Typen umgegangen wird:

#include
#include

int main ( ) {
std::any myAny = 42 ;

versuchen {

doppelter Wert = std::any_cast < doppelt > ( myAny ) ;
std::cout << 'Wert: ' << Wert << std::endl;
} fangen ( const std::bad_any_cast & Es ist ) {

std::cerr << 'Fehler: ' << e.was ( ) << std::endl;
}

zurückkehren 0 ;
}


Wir beginnen mit der Initialisierung der „std::any“-Variable „myAny“ mit dem Wert 42 des Integer-Typs. Im darauffolgenden „try“-Block versuchen wir explizit, diesen ganzzahligen Wert mithilfe der Operation „std::any_cast“ in ein „double“ umzuwandeln. Da der tatsächliche Typ, der in „myAny“ gespeichert ist, jedoch eine Ganzzahl ist, ist dieser Umwandlungsvorgang für ein „double“ ungültig, was zu einem nicht übereinstimmenden Typ führt.

Um diesen potenziellen Fehler ordnungsgemäß zu verwalten, implementieren wir die Ausnahmebehandlung mit einem „catch“-Block, der den spezifischen Ausnahmetyp „std::bad_any_cast“ abfangen soll. Im Falle eines erfolglosen Casts wird der „catch“-Block aktiviert und wir generieren eine Fehlermeldung mit „std::cerr“, um die Art des Fehlers mitzuteilen. Diese Fehlerbehandlungsstrategie stellt sicher, dass unser Programm Situationen, in denen die versuchte Typumwandlung mit dem tatsächlichen Typ kollidiert, der in der Variablen „std::any“ gespeichert ist, ordnungsgemäß bewältigen kann.

Abschluss

In diesem Artikel haben wir die Anwendungen von „std::any“ in C++ untersucht, einem dynamischen Typcontainer, der in C++ für Werte verschiedener Typen eingeführt wird. Wir haben seine Vielseitigkeit anhand verschiedener Beispiele demonstriert und Szenarien vorgestellt, die von der grundlegenden Verwendung bis zur Handhabung benutzerdefinierter Typen und heterogener Sammlungen reichen. Wir haben seine praktische Anwendung in Szenarien demonstriert, in denen der Datentyp zum Zeitpunkt der Kompilierung nicht bekannt ist. Darüber hinaus haben wir uns mit den Fehlerbehandlungstechniken befasst und dabei betont, wie wichtig es ist, die nicht unterstützten Typen durch Ausnahmebehandlung ordnungsgemäß zu verwalten.