using bytes = std::vector<std::byte>;
I would call it
Bytes to make it clear it is a type rather than an object.
This is not a good idea:
using namespace std;
See: Why is “using namespace std;” considered bad practice?
This is technically not valid C++.
Variable sized arrays (VSA) are an extension to the language supported by several compilers but not actually part of the C++ standard. Though it is part of the more recent versions C standard.
Also creating a local array means that the data is being created on the local stack frame (here I assuming a Von-Neumann like architecture). This means for the data to exist after the function completes means you will need to copy it out of the function. So an alternative data object is probably a good idea.
Also there is a limitation on the size of array allowed on the stack (there are hardware limitations on the size of stack frames on lots of architecture).
So a god idea would be to use the same data structure that you return.
Bytes data(length); // This is basically std::vector
Now in older versions of C++ there are some nice optimizations that can be applied to
std::vector when it is returned from a function that allow the compiler to build the
std::vector at the final destination so that it is not actually copied on return.
In modern versions of the compiler the language has the concept of move semantics built into the language. So returning a
std::vector is not an expensive operation as the internal buffer is moved (just the pointer is copied) from the function to the destination result.
Also the compiler is now required to perform copy elision of objects when it can.
This code does zero error checking. There are several things that can go wrong and you don't check for any of them. But you said you removed this (you should have left it in).
So a better version:
using Bytes = std::vector<std::byte>;
Bytes read_block(std::uint32_t offset,
std::string const& filename)
// Not going to explicitly check these.
// The use of gcount() below will compensate for a failure here.
std::ifstream is(filename, std::ios::binary);
// We have to check that reading from the stream actually worked.
// If any of the stream operation above failed then `gcount()`
// will return zero indicating that zero data was read from the
// Simply return the vector to allow move semantics take over.