I have 2 functions to read binary file.
1st function reads sizeof(T)
bytes from file:
template<typename T>
T read() { ... some IO operations ... };
2nd function calls first one multiple times with each template parameter:
template<typename... Ts>
std::tuple<Ts...> read_all() {
return std::make_tuple(read<Ts>()...);
};
Everything works fine except of 1st function call order. For something like
uint32_t a;
uint8_t b;
std::tie(a, b) = read_all<uint32_t, uint8_t>();
the first will be called read<uint8_t>()
and after that read<uint32>()
which reverses order of passing template parameters and messes up with order of bytes in file.
Sure, I can call read_all
with reversed order of template arguments and get right order in the end, but is there a more obvious way to do so?
C++ does not specify the order in which a function's arguments are evaluated. If the expressions to a function all consume data from a stream, you can get behavior where objects are read in the wrong order.
Braced initializer lists are evaluated from left to right, however, so you should get better results if you try something like:
template<typename... Ts>
std::tuple<Ts...> read_all() {
return std::tuple<Ts...>{read<Ts>()...};
}
I would keep it a bit simpler and do this:
uint32_t a;
uint8_t b;
std::tie(a, b) = read<std::tuple<uint32_t, uint8_t>>();
This way there's only a single read()
and you can even skip the tie()
if you use the tuple (or struct) fields directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With