簡體   English   中英

如何在需要舊式 unsigned char 的地方使用新的 std::byte 類型?

[英]How to use new std::byte type in places where old-style unsigned char is needed?

std::byte是 C++17 中的一種新類型,它被制成enum class byte: unsigned char 如果不進行適當的轉換,就無法使用它。 所以,我為這種類型的向量創建了一個別名來表示一個字節數組:

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

但是,不可能在舊式中使用它:接受它作為參數的函數會失敗,因為這種類型不能輕易轉換為舊的std::vector<unsigned char>類型,例如zipper庫的用法:

/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>&'

我曾嘗試執行天真的演員表,但這也無濟於事。 那么,如果它被設計成有用的,它在舊環境中是否真的有用? 我看到的唯一方法是使用std::transform在這些地方使用新的字節向量:

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;

這是:

  1. 丑陋。
  2. 占用了很多無用的行(可以重寫,但仍然需要先寫:))。
  3. 復制 memory 而不是僅僅使用已經創建的rawBytes塊。

那么,老地方怎么用呢?

你錯過了為什么std::byte被發明的原因。 它被發明的原因是在存儲器中保存一個原始字節而不假設它是一個字符 你可以在cppreference中看到它。

與char和unsigned char一樣,它可以用於訪問其他對象占用的原始內存(對象表示),但與這些類型不同,它不是字符類型,也不是算術類型。

請記住,為了安全起見,C ++是一種強類型語言(因此在許多情況下隱式轉換受到限制)。 含義:如果從bytechar的隱式轉換是可能的,那么它將失敗目的。

所以,要回答你的問題:要使用它,你必須在你想要分配時使用它:

std::byte x = (std::byte)10;
std::byte y = (std::byte)'a';
std::cout << (int)x << std::endl;
std::cout << (char)y << std::endl;

其他任何東西都不能按設計工作! 因此轉換是丑陋的,同意,但如果你想存儲字符,那么使用char 除非您希望存儲默認情況下不應解釋為char原始內存否則不要使用字節。

而且你問題的最后一部分通常也是錯誤的:你不必復制,因為你不必復制整個載體。 如果您暫時需要將byte讀取為char ,只需在需要將其用作char的位置進行static_cast 它沒有任何成本,而且是類型安全的。


關於將std::vector<char>std::vector<std::byte>的注釋中的問題,你不能這樣做。 但是你可以使用下面的原始數組。 所以,以下是一個類型(char*)

 std::vector<std::byte> bytes; // fill it... char* charBytes = reinterpret_cast<char*>(bytes.data()); 

這個類型為char* ,它是指向數組第一個元素的指針,可以在不復制的情況下解除引用,如下所示:

 std::cout << charBytes[5] << std::endl; //6th element of the vector as char 

以及從bytes.size()獲得的大小。 這是有效的,因為std::vector在內存中是連續的。 你通常不能用任何其他std容器(deque,list等)來做這件事。

雖然這是有效的,但它會從等式中消除部分安全性,請記住這一點。 如果需要char ,請不要使用byte

如果你想要的東西就像你可能期望的那樣行為,但命名與unsigned char明顯不同,請使用stdint.h中的uint8_t。 對於幾乎所有的實現,這可能是一個

typedef unsigned char uint8_t;

再次成為引擎蓋下的無符號字符 - 但是誰在乎呢? 你只想強調“這不是一個字符類型”。 您不必期望能夠對某些函數進行兩次重載,一次用於unsigned char,另一次用於uint8_t。 但是,如果你這樣做,編譯器會把你的鼻子推到它上面......

如果舊樣式代碼將范圍或迭代器作為參數,則可以繼續使用它們。 在少數情況下你不能(比如explicit的基於范圍的構造函數),你理論上可以編寫一個新的迭代器類,它將迭代器包裝到unsigned char並將*it轉換為std::byte&

如果你真的想這樣做並且你確定它是安全的,你可以使用指針轉換:

std::vector<std::byte> v;
void f(std::vector<unsigned char>& v);
f(*std::vector<unsigned char>*(&v));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM