C++17では、バイトを表現する型が入った。std::byteは<cstddef>で定義されている。ライブラリでもあるのだがコア言語で特別な型として扱われている。
バイトとはC++のメモリモデルにおけるストレージの単位で、C++においてユニークなアドレスが付与される最小単位だ。C++の規格は未だに1バイトが具体的に何ビットであるのかを規定していない。これは過去にバイトのサイズが8ビットではないアーキテクチャが存在したためだ。
バイトのビット数は<climits>で定義されているプリプロセッサーマクロ、CHAR_BITで知ることができる。
C++17では、1バイトはUTF-8の8ビットの1コード単位をすべて表現できると規定している。
C++では、1バイトのストレージはunsigned char型かstd::byte型で表現できる。複数バイトが連続するストレージは、unsigned charの配列型、もしくはstd::byteの配列型として表現できる。
std::byte型は、<cstddef>で以下のように定義されている。
namespace std
{
enum class byte : unsigned char { } ;
}
std::byteはライブラリとしてscoped enum型で定義されている。これにより、他の整数型からの暗黙の型変換が行えない。
値0x12のstd::byte型の変数は以下のように定義できる。
int main()
{
std::byte b{0x12} ;
}
std::byte型の値が欲しい場合は、以下のように書くことができる。
int main()
{
std::byte b{} ;
b = std::byte( 1 ) ;
b = std::byte{ 1 } ;
b = static_cast< std::byte >( 1 )
}
std::byte型は他の数値型からは暗黙に型変換できない。これによりうっかりと型を取り違えてバイト型と他の型を演算してしまうことを防ぐことができる。
int main()
{
// エラー、()による初期化はint型からの暗黙の変換が入る
std::byte b1(1) ;
// エラー、=による初期化はint型からの暗黙の変換が入る
std::byte b2 = 1 ;
std::byte b{} ;
// エラー、operator =によるint型の代入は暗黙の変換が入る
b = 1 ;
// エラー、operator =によるdouble型の代入は暗黙の変換が入る
b = 1.0 ;
}
std::byte型は{}によって初期化するが、縮小変換を禁止するルールにより、std::byte型が表現できる値の範囲でなければエラーとなる。
例えば、今std::byteが8ビットで、最小値が0、最大値が255の環境だとする。
int main()
{
// エラー、表現できる値の範囲ではない
std::byte b1{-1} ;
// エラー、表現できる値の範囲ではない
std::byte b2{256} ;
}
std::byteは一部の演算子がオーバーロードされているので、通常の整数型のように使うことができる。ただし、バイトをビット列演算するのに使う一部の演算子だけだ。
具体的には、以下に示すシフト、ビットOR、ビット列AND、ビット列XOR、ビット列NOTだ。
<<= <<
>>= >>
|= |
&= &
^= ^
~
四則演算などの演算子はサポートしていない。
std::byteはstd::to_intenger<IntType>(std::byte)により、IntType型の整数型に変換できる。
int main()
{
std::byte b{42} ;
// int型の値は42
auto i = std::to_integer<int>(b) ;
}