I want to write/read a tuple into a BIN file. I know how to write/read each element of the tuple, but the tuple has 13 elements and I would rather make this all at once using a loop. But I have been unable to do so.
This is the code that I have tried:
#include <fstream>
template <typename T>
std::ostream& writeBin(std::ostream& f, T data) {
return f.write(reinterpret_cast<char*>(&data), sizeof(data));
}
std::ostream& writeBin(std::ostream& f, const std::string& str) {
std::string::size_type sz = str.size();
if (f) { f.write(reinterpret_cast<char*>(&sz), sizeof(sz)); }
if (f) { f.write(str.data(), str.size()); }
return f;
}
template <typename T>
std::istream& readBin(std::istream& f, T& data) {
if (f) { f.read(reinterpret_cast<char*>(&data), sizeof(data)); }
return f;
}
std::istream& readBin(std::istream& f, std::string& str) {
std::string::size_type sz = 0;
if (f) { f.read(reinterpret_cast<char*>(&sz), sizeof(sz)); }
if (f) { str.resize(sz); f.read(str.data(), sz); }
return f;
}
class Data {
public:
Data() {};
~Data() {};
std::tuple<std::string, std::string, int, int, int, int, std::string, int, int, int, int, int, int>tup{
" "," ",0,0,0,0," ",0,0,0,0,0,0
};
bool write(std::ofstream& f);
bool read(std::ifstream& f);
};
bool Data::write(std::ofstream& f) {
std::apply([](auto&&... tArg) {
((if (!writeBin(f, tArg)) { return false; }), ...);//doesnt work
}, tup);
return true;
}
bool Data::read(std::ifstream& f) {
std::apply([](auto&&... tArg) {
((if (!readBin(f, tArg)) { return false; }), ...);//doesnt work
}, tup);
return true;
}
Do you mean iterating over all the elements of tuple?
That's what std::index_sequence
is for:
C++20:
bool Data::write(std::ostream& f) {
using Tuple = decltype(tup);
return [&os=f]<std::size_t...I> (const auto& tup, std::index_sequence<I...>){
return (writeBin(os, std::get<I>(tup)) && ...);
}(tup, std::make_index_sequence<std::tuple_size_v<Tuple>>());
}
Pre-C++20 you need to provide an extra helper layer, but the principle is generally the same:
template<typename Tuple, std::size_t...I>
static bool write_impl(
std::ostream& f,
const Tuple& t,
std::index_sequence<I...>)
{
return (writeBin(f, std::get<I>(t)) && ...);
}
bool Data::write(std::ostream& f) {
return write_impl(f, tup, std::make_index_sequence<std::tuple_size_v<decltype(tup)>>());
}