2017-05-14 4 views
1

Ich habe eine Frage über boost::variant und korrekte Verwendung davon in Methoden. Zum Beispiel habe ich Klassen wie Stuff und User und ich habe Funktion (Pseudocode):Boost Variante Rückgabetyp

boost::variant<User*, Stuff*> HashTable::getPersonByKey(string login, string password, string list_type) 
    { 
    int index = hash(login, password); 
    boost::variant<User*, Stuff*> temp_u, temp_s; 
    if (list_type == "User") 
    { 
     if (user_array[index].getPerson(login, password)) 
     { 
      temp_u = user_array[index].getPerson(login, password); 
      //returns User* 
      //maybe something like variant<User* , Stuff*> (temp_u); 
      return VARIANT 
     } 
    } 
    else if (list_type == "Stuff") 
    { 
     if (user_array[index].getPerson(login, password)) 
     { 
      temp_s = stuff_array[index].getPerson(login, password); 
      //returns Stuff* 
      //maybe something like variant<User* , Stuff*> (temp_s); 
      return VARIANT 
     } 
    } 
    return boost::variant<User*, Stuff*>(); 
} 

Wie wird die Rückkehr sein soll?

Kann ich etwas noch komplexere wie ...

boost::variant<boost::variant<User*, Stuff*>, boost::variant<User*, Stuff*>>getPerson() 
{ 
    boost::variant<boost::variant<User*, Stuff*>, boost::variant<User*, Stuff*>> temp_user1, temp_stuff1 , 
    temp_user2 , temp_stuff2; 
    temp_u = user_array[index].getPerson(login, password); 
    return variant<variant <User* , Stuff*> ,variant <User* , Stuff*>> (temp_user1); 
} 

Soll ich zeigen irgendwie explizit auf die Variante temp_person gehört? Wird es ein Problem sein, Objekte daraus zu machen?

+1

Wollen Sie nicht stattdessen Vererbung? – Jarod42

+1

In 'boost :: variant , boost :: variant >' sind die 2 Typen identisch, für 'variant' ergibt das keinen Sinn . – Jarod42

+0

'return user_array [index] .getPerson (Login, Passwort);' oder 'return temp_u;' sollte funktionieren. – Jarod42

Antwort

1

Sie können über boost::variant als eine verbesserte C++ union denken.

Zum Beispiel, als union kann boost::variant<User*, Stuff*> speichern entweder einen Zeiger auf User oder einen Zeiger auf Stuff aber im Gegensatz zu einem union, können Sie überprüfen, welche Art gespeichert ist.

In Ihrem Beispiel Sie erklären:

boost::variant<User*, Stuff*> getPersonByKey(string login, string password, string list_type) 

Es bedeutet, dass getPersonByKey gibt entweder ein User* oder ein Stuff*. Sie können eine Variante aus einer ihrer Optionen konstruieren, sodass Sie nur einen Zeiger dieser Typen zurückgeben können.

Die Methode getPerson() ist in Ihrem Beispiel nicht deklariert, daher kann ich Ihr Beispiel nicht vollständig umschreiben. Wenn getPerson() jedoch einen User* zurückgibt, können Sie den Wert direkt zurückgeben, und dieser Wert wird in einen boost::variant<User*, Stuff*> konvertiert, der den zurückgegebenen Wert enthält.

Beachten Sie, dass boost::variant<User*, Stuff*> sein muss entweder User* oder Stuff*. Es kann nicht leer sein. Wenn Sie also einen Standardwert boost::variant<User*, Stuff*> zurückgeben, geben Sie einen Standardzeiger an User zurück.

Als boost :: Variante verwendet wird, eine der Template-Parameter zu halten, macht es keinen Sinn zu erklären, es mag:

boost::variant<T, T> 

Weil es bedeutet, dass Sie entweder ein T speichern oder und T. In In diesem Fall können Sie einfach einen T-Typ verwenden.

Es ist sehr einfach zu überprüfen, welcher Typ in der Variante gespeichert ist. Der einfachste Weg ist es, die get Methode zu verwenden:

User **user = boost::get<User*>(&variant); 

Die Variablen user einen Zeiger auf den gespeicherten Wert, wenn ein Zeiger auf User gespeichert wurde oder nullptr wenn ein Stuff Zeiger gespeichert wurde. Es gibt mehrere Möglichkeiten, auf den Wert zuzugreifen, z. B. die Verwendung von Besuchern.

Weitere Informationen finden Sie in der variant tutorial.

Verwandte Themen