yohhoyの日記

技術的メモをしていきたい日記

std::byte型あれこれ

C++1z(C++17)で導入されるstd::byte型に関するメモ。

コンパイル時型検査による安全性向上を目的として、「バイト(byte)」を表す標準データ型として導入される。C++標準ライブラリの拡張だけではなく、C++言語仕様にも特別扱いが追加される。

// 標準ヘッダ<cstddef>
namespace std {
  enum class byte : unsigned char {};
}

まとめ:

  • 標準ヘッダ<cstddef>:後述の演算子オーバーロードや変換関数も同ヘッダで定義される。
  • ビット演算サポート:左シフト(<<)、右シフト(>>)、AND(&)、OR(|)、XOR(^)、反転(~)、複合代入演算(<<=, >>=, &=, |=, ^=)。constexpr修飾あり。
  • 整数型/文字型からstd::byte型への変換:std::byte{i}。暗黙にconstexpr修飾あり。
    • 縮小変換(narrowing conversion)が生じる場合はill-formedとなる。
    • “underlaying型明示した列挙型の直接リスト初期化(direct-list-initialization)” はC++1zでの追加仕様。*1
  • std::byteから整数型/文字型への変換:std::to_integer<IntegerType>(b)。constexpr修飾あり。
  • 動的メモリ確保のアライメント要件:char型、unsigned char型と同じ扱いのため、基本的なアライメント(fundamental alignment)要件を満たす。
    • new std::byte[N]等で確保したメモリ領域に対して、double型などの基本型を安全に格納できる。
  • Strict Aliasing Rule:char型、unsigned char型と同じ扱いのため、任意の型Tと安全に相互変換を行える(→id:yohhoy:20120220)。
    • ポインタ/参照を経由した型キャストにより、std::byte型配列をT型オブジェクトとみなしてアクセス/T型オブジェクトをstd::byte型配列とみなしてアクセスして良い。ただしアライメント要件は別途満たすこと。
  • 言語仕様上はstd::byteが厳密に8ビット幅とは限らず、8ビット以上であることしか要求しない。unsigned char型と同じ。
    • 厳密に8ビット幅整数型が必要であれば、std::int8_tまたはstd::uint8_tを用いること。

N4659(C++1z DIS) 6.10/p8, 8.3.4/p10, 11.6.4/p3より一部引用(下線部は強調)。

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • (snip)
  • a char, unsigned char, or std::byte type.

When a new-expression calls an allocation function and that allocation has not been extended, the new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. (snip) For arrays of char, unsigned char, and std::byte, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement (6.11) of any object type whose size is no greater than the size of the array being created. (snip)

List-initialization of an object or reference of type T is defined as follows:

  • (snip)
  • Otherwise, if T is an enumeration with a fixed underlying type (10.2), the initializer-list has a single element v, and the initialization is direct-list-initialization, the object is initialized with the value T(v) (8.2.3); if a narrowing conversion is required to convert v to the underlying type of T, the program is ill-formed. [Example:
enum byte : unsigned char { };
byte b { 42 };          // OK
byte c = { 42 };        // error
byte d = byte{ 42 };    // OK; same value as b 
byte e { -1 };          // error

struct A { byte b; };
A a1 = { { 42 } };      // error
A a2 = { byte{ 42 } };  // OK

void f(byte);
f({ 42 });              // error

enum class Handle : uint32_t { Invalid = 0 };
Handle h { 42 };        // OK

-- end example]

  • (snip)

関連URL