Ich habe Probleme beim Schreiben einer Funktion, die eine Sammlung von Strings als Parameter akzeptiert. Meine Funktion sieht so aus:
%Vor% Alles geht gut, wenn ich ein Vec<&'a str>
wie erwartet an die Funktion übergebe. Wenn ich jedoch ein Vec<String>
übergebe, beschwert sich der Compiler:
Dies wird hauptsächlich verwendet:
%Vor% Meine Funktion kann keine Vektoren von eigenen Strings aufnehmen. Umgekehrt, wenn ich den Typ StrList
in:
Der erste Aufruf schlägt fehl und der zweite funktioniert.
Eine mögliche Lösung besteht darin, auf diese Weise ein Vec<&'a str>
von v2
zu erzeugen:
Aber es scheint mir sehr seltsam. my_func
sollte sich nicht um den Besitz der Zeichenfolgen kümmern.
Welche Art von Signatur sollte ich für my_func
verwenden, um beide Vektoren von eigenen Strings und String-Referenzen zu unterstützen?
Obwohl String
und &str
sehr eng verwandt sind, sind sie nicht identisch. Hier sehen Sie, wie Ihre Vektoren im Speicher aussehen:
Hier ist jede Zeile die gleiche Menge an Speicher (vier oder acht Bytes je nach Zeigergröße). Du kannst nicht die Erinnerung an eine von diesen nehmen und sie wie die andere behandeln. Das Speicherlayout stimmt nicht überein. Die Artikel sind unterschiedlich groß und haben ein unterschiedliches Layout. Wenn beispielsweise v1
seine Artikel ab der Adresse X
speichert und v2
seine Artikel ab der Adresse Y
speichert, dann ist v1[1]
auf der Adresse X + 8
, aber v2[1]
auf der Adresse Y + 12
.
Was Sie tun können schreiben Sie eine generische Funktion wie folgt:
%Vor% Dann kann der Compiler entsprechenden Code sowohl für &[String]
und &[&str]
als auch für andere Typen generieren, wenn sie AsRef<str>
implementieren.
Um auf delnans großer Antwort aufzubauen, möchte ich auf eine weitere Ebene von Generika hinweisen, die Sie hier hinzufügen können. Du hast gesagt:
eine Sammlung von Strings
Aber es gibt mehr Arten von Sammlungen als Schnitte und Vektoren! In Ihrem Beispiel geht es Ihnen um den einmaligen Zugriff auf die Elemente. Dies ist ein perfektes Beispiel für Iterator
. Im Folgenden habe ich Ihre Funktion so geändert, dass sie jeden Typ akzeptiert, der in einen Iterator umgewandelt werden kann. Sie können dann viele weitere Arten von Dingen passieren. Ich habe ein HashSet
als Beispiel verwendet, aber beachten Sie, dass Sie auch v1
und v2
anstelle von &v1
oder &v2
übergeben können, indem Sie sie verbrauchen.