Search code examples
c++iobytec++17binaryfiles

Unable to read a binary file into std::vector<std::byte> in C++


I am trying to read a .WAV file in C++ into a vector of binary data:

typedef std::istreambuf_iterator<char> file_iterator;

std::ifstream file(path, std::ios::in | std::ios::binary);
if (!file.is_open()) {
    throw std::runtime_error("Failed to open " + path);
}

std::vector<std::byte> content((file_iterator(file)), file_iterator());

When I attempt to compile this code I get an error:

Cannot convert 'char' to 'std::byte' in initialization

However if I change the vector to std::vector<unsigned char> it works fine.

Looking at the documentation for std::byte it looks like it is supposed to act like an unsigned char so I'm not sure where the compiler is getting confused.

Is there any particular way you are supposed to go about reading a file into a vector of bytes? (I am looking for a modern C++ approach)


I am using MinGW 7.3.0 as my compiler.

EDIT:

This question is not a duplicate because I am specifically concerned about modern C++ techniques and the use of std::byte which is not discussed in that question.


Solution

  • std::byte is a scoped enum. As such, there are restrictions on conversion to the type that do not exist for fundamental types like char.

    Because the underlying type of std::byte is unsigned char, you can't convert a (signed) char to a byte during initialization because the conversion is a narrowing conversion.

    One solution is to use a vector of unsigned char to store the file content. Since a byte is not an arithmetic type, many of the numeric operations do not exist for byte (only the bitwise ones).

    If you must use std::byte, define the iterator and fstream using that type:

    typedef std::istreambuf_iterator<std::byte> file_iterator;
    
    std::basic_ifstream<std::byte> file(path, std::ios::in | std::ios::binary);