web-dev-qa-db-ja.com

古いスタイルのunsigned charが必要な場所で新しいstd :: byte型を使用する方法は?

std::byteは、C++ 17の新しい型で、enum class byte : unsigned charとして作成されます。これにより、適切な変換なしでは使用できなくなります。そこで、バイト配列を表すために、そのような型のベクトルのエイリアスを作成しました。

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

ただし、古いスタイルで使用することはできません。たとえば、zipperライブラリの使用法のように、このタイプを古いstd::vector<unsigned char>タイプに簡単に変換できないため、パラメーターとして受け入れる関数は失敗します。

/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. 既に作成されたrawBytesのチャンクを使用する代わりに、メモリをコピーします。

それで、古い場所でそれを使用する方法は?

28
Victor Polevoy

古いスタイルのコードが引数として範囲またはイテレータを使用する場合、それらを引き続き使用できます。できない場合(explicit範囲ベースのコンストラクターなど)では、理論的にはイテレーターをunsigned charにラップし、*itstd::byte&に変換する新しいイテレータークラスを作成できます。

0
Davislor

おそらく期待どおりにバイトのように動作するが、unsigned charとは明らかに異なる名前が付けられているものが必要な場合は、stdint.hのuint8_tを使用します。ほとんどすべての実装では、これはおそらく

typedef unsigned char uint8_t;

そして再びボンネットの下にある無署名のイワナ-誰が気にしますか? 「これは文字タイプではありません」を強調したいだけです。いくつかの関数の2つのオーバーロード、1つはunsigned char用、もう1つはuint8_tを持つことができることを期待する必要はありません。しかし、コンパイラを実行すると、とにかく鼻を押してしまいます...

0
Don Pedro