webentwicklung-frage-antwort-db.com.de

Wie verwende ich den neuen std :: byte-Typ an Stellen, an denen vorzeichenlose Zeichen im alten Stil benötigt werden?

std::byte Ist ein neuer Typ in C++ 17, der als enum class byte : unsigned char Erstellt wird. Dies macht es unmöglich, es ohne entsprechende Konvertierung zu verwenden. Daher habe ich einen Alias ​​für den Vektor dieses Typs erstellt, der ein Byte-Array darstellt:

using Bytes = std::vector<std::byte>;

Es ist jedoch unmöglich, es im alten Stil zu verwenden: Die Funktionen, die es als Parameter akzeptieren, schlagen fehl, weil dieser Typ nicht einfach in einen alten std::vector<unsigned char> - Typ konvertiert werden kann, z. B. eine Verwendung von zipper Bibliothek:

/resourcecache/pakfile.cpp: In member function 'utils::Bytes resourcecache::PakFile::readFile(const string&)':
/resourcecache/pakfile.cpp:48:52: error: no matching function for call to 'zipper::Unzipper::extractEntryToMemory(const string&, utils::Bytes&)'
     unzipper_->extractEntryToMemory(fileName, bytes);
                                                    ^
In file included from /resourcecache/pakfile.hpp:13:0,
                 from /resourcecache/pakfile.cpp:1:
/projects/linux/../../thirdparty/zipper/zipper/unzipper.h:31:10: note: candidate: bool zipper::Unzipper::extractEntryToMemory(const string&, std::vector<unsigned char>&)
     bool extractEntryToMemory(const std::string& name, std::vector<unsigned char>& vec);
          ^~~~~~~~~~~~~~~~~~~~
/projects/linux/../../thirdparty/zipper/zipper/unzipper.h:31:10: note:   no known conversion for argument 2 from 'utils::Bytes {aka std::vector<std::byte>}' to 'std::vector<unsigned char>&'

Ich habe versucht, naive Casts durchzuführen, aber das hilft auch nicht. Also, wenn es nützlich sein soll, wird es tatsächlich in alten Kontexten nützlich sein? Die einzige Methode, die ich sehe, ist die Verwendung von std::transform Für die Verwendung eines neuen Vektor von Bytes an folgenden Stellen:

utils::Bytes bytes;
std::vector<unsigned char> rawBytes;
unzipper_->extractEntryToMemory(fileName, rawBytes);
std::transform(rawBytes.cbegin(),
               rawBytes.cend(),
               std::back_inserter(bytes),
               [](const unsigned char c) {
                   return static_cast<std::byte>(c);
               });
return bytes;

Welches ist:

  1. Hässlich.
  2. Nimmt viele nutzlose Zeilen (kann umgeschrieben werden, muss aber vorher noch geschrieben werden :)).
  3. Kopiert den Speicher, anstatt nur den bereits erstellten Teil von rawBytes zu verwenden.

Also, wie benutzt man es an alten Orten?

28
Victor Polevoy

Wenn Ihr alter Code Bereiche oder Iteratoren als Argumente verwendet, können Sie diese weiterhin verwenden. In den wenigen Fällen, in denen dies nicht möglich ist (z. B. bei auf explicit Bereichen basierenden Konstruktoren), können Sie theoretisch eine neue Iteratorklasse schreiben, die einen Iterator in unsigned char Umschließt und *it Konvertiert. zu std::byte&.

0
Davislor

Wenn Sie möchten, dass sich etwas wie ein Byte so verhält, wie Sie es wahrscheinlich erwarten würden, das jedoch einen anderen Namen trägt als nicht signiertes Zeichen, verwenden Sie uint8_t von stdint.h. Für fast alle Implementierungen wird dies wahrscheinlich ein

typedef unsigned char uint8_t;

und wieder ein unsignierter char unter der haube - aber wen interessiert das schon? Sie möchten nur "Dies ist kein Zeichentyp" hervorheben. Sie müssen einfach nicht damit rechnen, dass einige Funktionen zweimal überladen werden können, eine für unsigned char und eine für uint8_t. Aber wenn Sie das tun, wird der Compiler Ihre Nase trotzdem darauf schieben ...

0
Don Pedro