SQLite - unique_ptr
-
Hi,
ich arbeite mich im Moment in SQLite ein.
Meine Frage hat aber eher weniger mit SQLite zutun, sondern eher allgemein mit Smartpointern:
Wie greife ich auf das eigendliche Objekt hinter einem SmartPointer zu?
std::unique_ptr<sqlite3> Database; [...] //Hier komme ich nicht weiter... int rc = sqlite3_open_v2(filename.c_str(), &this->Database, flags, NULL); LastError =(std::string)sqlite3_errmsg(this->Database);
Die Fehlermeldung ist immer
IntelliSense: Es ist keine passende Konvertierungsfunktion von ""std::unique_ptr<sqlite3, std::default_delete<sqlite3>>"" in ""sqlite3 *"" vorhanden.
Kann mir da jemand weiterhelfen?
-
Auf den Inhalt eines Smart-Pointers greift man mit der
get
-Memberfunktion zu, hier wäre das std::unique_ptr::get. Auf den Pointee greift man wie gewohnt über den (für Smart-Pointer überladenen) *-Operator oder ->-Operator zu.Dein Code hat aber das Problem dass
sqlite3_open_v2
einen Zeiger auf den Zeiger erwartet. Man kann den internen Zeiger eines Smart-Pointers aber nicht direkt anfassen. Da musst du irgendwie einen Zeiger zum Zwischenspeichern verwenden.
-
Hi,
error C2664: 'sqlite3_open_v2': Konvertierung des Parameters 2 von 'std::unique_ptr<_Ty> *' in 'sqlite3 **' nicht möglich
error C2664: 'sqlite3_errmsg': Konvertierung des Parameters 1 von 'std::unique_ptr<_Ty>' in 'sqlite3 *' nicht möglich
-
Probier es mal so
sqlite3* ptr; int rc = sqlite3_open_v2(filename.c_str(), &ptr, flags, NULL); Database.reset(ptr);
LastError =(std::string)sqlite3_errmsg(Database.get()); // Das sollte funktionieren
-
Was willst du denn da mit einem unique_ptr? Du musst zum Freigeben die passende sqlitv3_close-Funktion verwenden!
-
LastError =(std::string)sqlite3_errmsg(Database.get());
Das passt so mit Sicherheit auch nicht. Und wenn´s doch funktioniert hast du Glück mit der Implementation, aber darauf würde ich nicht nicht verlassen.
sqlite3_errmsg
liefert etwas zurück, was sich in einenstd::string
konvertieren lässt, aber es ist mit Sicherheit keinstd::string
.
-
DocShoe schrieb:
LastError =(std::string)sqlite3_errmsg(Database.get());
Das passt so mit Sicherheit auch nicht. Und wenn´s doch funktioniert hast du Glück mit der Implementation, aber darauf würde ich nicht nicht verlassen.
sqlite3_errmsg
liefert etwas zurück, was sich in einenstd::string
konvertieren lässt, aber es ist mit Sicherheit keinstd::string
.Es liefert einen
char const*
zurück. Keinvoid const*
, wiesqlite3_errmsg16
. Dann wird einstd::string
mit dem zurückgegebenen, nullterminiertem(?) String initialisiert. Wo genau liegt das Problem, übersehe ich etwas?
-
manni66 schrieb:
Was willst du denn da mit einem unique_ptr? Du musst zum Freigeben die passende sqlitv3_close-Funktion verwenden!
Auch in dem Fall ist ein unique_ptr hilfreich. Man muss nur die sqlitv3_close-Funktion als custom deleter verwenden.
-
Arcoth schrieb:
DocShoe schrieb:
LastError =(std::string)sqlite3_errmsg(Database.get());
Das passt so mit Sicherheit auch nicht. Und wenn´s doch funktioniert hast du Glück mit der Implementation, aber darauf würde ich nicht nicht verlassen.
sqlite3_errmsg
liefert etwas zurück, was sich in einenstd::string
konvertieren lässt, aber es ist mit Sicherheit keinstd::string
.Es liefert einen
char const*
zurück. Keinvoid const*
, wiesqlite3_errmsg16
. Dann wird einstd::string
mit dem zurückgegebenen, nullterminiertem(?) String initialisiert. Wo genau liegt das Problem, übersehe ich etwas?Nach dem zweiten mal drüber nachdenken hast du recht. Ich bin irgendwie davon ausgegangen, dass sich der C-Style cast wie ein reinterpret_cast verhält, und dann wäre das Verhalten implementationsabhängig.
-
DocShoe schrieb:
Nach dem zweiten mal drüber nachdenken hast du recht. Ich bin irgendwie davon ausgegangen, dass sich der C-Style cast wie ein reinterpret_cast verhält, und dann wäre das Verhalten implementationsabhängig.
Ist meier Meinung nach auch eher unschöner Code Ich hätte eher etwas geschrieben wie
LastError = std::string{sqlite3_errmsg(Database.get()};
-
Wozu denn ueberhaupt ein Cast, ist er wirklich noetig? Und warum 'Uniform Initialization', TNA?
@DocShoe: Ist dir die Semantik von C-Style Casts in C++ klar? Sie haben das gleiche Verhalten wie ein
static_cast
, falls moeglich. Nur falls dieser nicht anwendbar ist kommtreinterpret_cast
zum Einsatz. (Das ist nicht ganz korrekt, aber ich werde nicht eine Beschreibung die const_cast beinhaltet auf einem alten Blackberry schreiben, das ist pure Folter :D)
-
Arcoth schrieb:
Wozu denn ueberhaupt ein Cast, ist er wirklich noetig?
Guter Punkt. Da string::string (const char* s) nicht explizit ist, sollte die Zuweisung auch ohne Cast funktionieren. Meiner Meinung nach die beste Variante.
Arcoth schrieb:
Und warum 'Uniform Initialization', TNA?
Ist sicherlich Geschmackssache aber warum nicht (mal davon abgesehen, dass an der Stelle eigentlich gar keine explizite Typumwandlung nötig ist)? Ich benutze immer Uniform Initialization dort wo es möglich ist.
-
TNA schrieb:
Ich benutze immer Uniform Initialization dort wo es möglich ist.
Ich hatte gehofft, das Forum haette allen derlei Schabernack ausgetrieben.
-
Arcoth schrieb:
TNA schrieb:
Ich benutze immer Uniform Initialization dort wo es möglich ist.
Ich hatte gehofft, das Forum haette allen derlei Schabernack ausgetrieben.
Eine lautstarke Minderheit überzeugt halt nicht jeden.