Skip to content

Instantly share code, notes, and snippets.

@sasq64
Last active May 7, 2018 13:08
Show Gist options
  • Save sasq64/6e5e431824597fd2bdfcb8a0c4c5098e to your computer and use it in GitHub Desktop.
Save sasq64/6e5e431824597fd2bdfcb8a0c4c5098e to your computer and use it in GitHub Desktop.
Serialization
#include <string>
#include <tuple>
#include <cstdio>
template<typename UnaryFunction>
void invoke_with_arg(UnaryFunction)
{}
/**
* Invoke the unary function with each of the arguments in turn.
*/
template<typename UnaryFunction, typename Arg0, typename... Args>
void invoke_with_arg(UnaryFunction f, Arg0&& a0, Args&&... as)
{
f(std::forward<Arg0>(a0));
invoke_with_arg(std::move(f), std::forward<Args>(as)...);
}
template<typename Tuple, typename UnaryFunction, std::size_t... Indices>
void for_each_helper(Tuple&& t, UnaryFunction f, std::index_sequence<Indices...>)
{
using std::get;
invoke_with_arg(std::move(f), get<Indices>(std::forward<Tuple>(t))...);
}
/**
* Invoke the unary function for each of the elements of the tuple.
*/
template<typename Tuple, typename UnaryFunction>
void for_each(Tuple&& t, UnaryFunction f)
{
using size = std::tuple_size<typename std::remove_reference<Tuple>::type>;
for_each_helper(
std::forward<Tuple>(t),
std::move(f),
std::make_index_sequence<size::value>()
);
}
template <class... Ts>
using void_t = void;
template <class T, class=void> struct has_fields : std::false_type{};
template <class T> struct has_fields<T, void_t<decltype(std::declval<T>().fields())>> : std::true_type{};
template <class T, class=void> struct has_pre : std::false_type{};
template <class T> struct has_pre<T, void_t<decltype(std::declval<T>().pre_serialize())>> : std::true_type{};
template <typename T> void Write(FILE *fp, const T& t) {
fwrite(&t, 1, sizeof(T), fp);
}
template <> void Write(FILE *fp, const std::string& t) {
Write(fp, t.length());
fwrite(&t[0], 1, t.length(), fp);
}
template <class T, std::enable_if_t<has_fields<T>::value>* = nullptr>
void write_all(FILE *fp, T& t)
{
for_each(t.fields(), [=](auto x) {
Write(fp, x);
});
}
template <class T, std::enable_if_t<!has_fields<T>::value>* = nullptr>
void write_all(FILE *fp, const T& t)
{
Write(fp, t);
}
template <class T, std::enable_if_t<has_pre<T>::value>* = nullptr>
void serialize(FILE *fp, T& t)
{
t.pre_serialize();
write_all(fp, t);
}
template <class T, std::enable_if_t<!has_pre<T>::value>* = nullptr>
void serialize(FILE *fp, T& t)
{
write_all(fp, t);
}
////
struct Test {
int a;
char b;
std::string d;
float c;
int _private;
void pre_serialize() {
printf("PRE SER!\n");
d = "hello";
}
auto fields() {
return std::tie(a,b,c,d);
}
};
int main()
{
Test t;
auto* fp = fopen("test.dat", "wb");
serialize(fp, t);
fclose(fp);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment