2017-06-11 1 views
3

Ich habe eine Funktion, die ein std::vector von Doppel-, und kopiert sie auf einem anderen Vektor, aber an einem bestimmten Offset (davon ausgeht, gibt es genügend Platz) nimmt:C++: Was ist der richtige Cast für Offseting nach Std :: Vector Iterator?

void copy_stuff(const std::vector<double> & data, 
       std::vector<double> & dest, 
       size_t dest_offset) { 
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset); 
} 

Dies führt zu einem C++ 11 Klirren Compiler -Weverything Warnung zentriert auf dem + dest_offset Teil:

Implicit conversion changes signedness: 'size_t' (aka 'unsigned long') to 'difference_type' (aka 'long').

ich bin nicht sicher, wie ich sollte den Ausdruck dest.begin() + dest_offset gegossen, um diese Warnung zu beseitigen. Gieße das Ergebnis in ein double * nicht kompilieren:

std::copy(data, data + data_size, static_cast<double *>(dest.begin() + dest_offset)); 

Cannot cast from type 'std::__1::__wrap_iter' to pointer type 'double *'.

Ich hatte mit Vektor Indizierung betrachtet und dann unter der Adresse:

std::copy(data, data + data_size, &dest[dest_offset]); 

Dies scheint die Warnung in diesem Fall zu beseitigen, aber kompiliert nicht, wenn ich versuche, das gleiche Muster mit dem Quellvektor zu verwenden, dh mit einem Offset, der am ersten oder zweiten Parameter von std::copy beteiligt ist. Zum Beispiel:

static void copy_stuff_differently(const std::vector<double> & data, 
            std::vector<double> & dest, 
            size_t offset) { 
    std::copy(data.begin() + offset, data.end(), dest.begin()); 
} 

Bietet die gleiche ursprüngliche Warnung der impliziten Konvertierung auf den + offset. Der Versuch, die Adresse-Index könnte darauf hindeuten, zu verwenden:

std::copy(&data[offset], data.end(), dest.begin()); 

Oder einen anderen, aber ähnlichen Fall:

std::copy(data.begin(), &data[offset], dest.begin()); 

jedoch beide einen ähnlichen Fehler verursachen:

test.cpp:8:3: error: no matching function for call to 'copy' 
    std::copy(&data[offset], data.end(), dest.begin()); 
    ^~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:1286:48: note: 
     candidate template ignored: deduced conflicting types for parameter '_Ip' ('const double *' vs. 
     'std::__1::__wrap_iter<const double *>') 
    template <class _Ip, class _Op> friend _Op copy(_Ip, _Ip, _Op); 
              ^

Ich bin auf der Suche nach einem konsistenten und warnfreien Weg, mit solchen Offsets umzugehen. Was ist der richtige Weg, um Offsets in einem Vektor zu handhaben und solche Fehler und Warnungen zu vermeiden?

+1

Clang-Entwickler sagen sehr explizit, dass Sie *** -Weverything *** nicht verwenden sollten. –

+0

tut 'std :: next (std :: begin(), dest_offset)' irgend etwas ändern? –

Antwort

3

I'm not sure how I should cast the expression dest.begin() + dest_offset in order to eliminate this warning.

Die Warnung nur sagen Ihnen, dass dest_offset erwartet wird, von der Art sein std::vector::difference_type, aber es ist size_t.

Sie können die Konvertierung explizit ausführen, um die Warnung zu eliminieren (beachten Sie, dass das Ergebnis, wenn der Quellwert nicht in difference_type dargestellt werden kann, implementierungsdefiniert ist). z.B.

dest.begin() + static_cast<std::vector<double>::difference_type>(dest_offset) 

Oder erklären Sie den Parameter dest_offset mit dem Typ difference_type von Anfang an.

Beachten Sie, dass std::vector::difference_type ein vorzeichenbehafteter Integertyp ist (normalerweise std::ptrdiff_t), der sich von size_t unterscheidet; Dies ist ein vorzeichenloser Integertyp.

+6

Ich würde sagen, dass der Parameter vom Typ 'std :: vector :: difference_type' sein sollte und nicht' size_t', um damit zu beginnen. –

+0

Ist 'std :: next (dest.begin(), dest_offset)' die Warnung zu vermeiden? Ich habe keinen Klang, um es jetzt zu testen. – Blastfurnace

+0

@Blastfurnace 'std :: next 'erwartet auch einen' difference_type'. – songyuanyao

4

Sie einigedifference_type verwenden können diese Warnung alle zusammen zu vermeiden:

#include<vector> 

using difference_type = std::vector<double>::difference_type; 

void copy_stuff(const std::vector<double> & data, 
       std::vector<double> & dest, 
//    size_t dest_offset) 
       difference_type dest_offset) 
{ 
    std::copy(data.begin(), data.end(), dest.begin() + dest_offset); 
} 

Es heutzutage weit verbreitet angenommen wird [Bearbeiten], dass die Berichterstattung/Größen und einige Versetzungen als unsigned Integer-Typen verwendet wurde ein Fehler im Design der Standard Library. Meiner Meinung nach ist es das Beste, diese Konvention nicht zu befolgen und unsignierte Typen so schnell wie möglich aus der Standardbibliothek zu ziehen, anstatt die Funktion so anzupassen, dass sie unsignierte Typen verwendet.

Zum Beispiel copy_stuff(a.begin(), a.end(), static_cast<difference_type>(other.size())).

+0

Danke, ich überlege dir, ob du das benutzen kannst - erste Experimente zeigen, dass es tatsächlich viele Warnungen verschwinden lässt. – meowsqueak

+0

sollten Sie dann nicht überprüfen, dass 'dest_offset> = 0'? – Walter

+0

@Walter Leider ist es ein Fehler, zu denken, dass der positive Wert sinnvoll ist, weil der Typ unsigniert ist. Wenn Sie eine negative Zahl zur Funktion füttern, wird sie in eine große positive Zahl umgewandelt, was ebenfalls keinen Sinn ergibt. Das einzige, was Sie tun, wenn Sie einen unsignierten Typ verwenden, ist das Ausblenden des Fehlers. Ich sage "leider", weil es einen mathematischen Sinn macht, aber in der Praxis funktioniert es nicht, weil "unsigned types" wirklich ein schlechter Name für "modulo types" sind. Sie können diese Überprüfung hinzufügen, aber es kostet Sie, es ist besser, sicherzustellen, dass die Programmlogik sinnvoll ist. – alfC

Verwandte Themen