#include <tuple> #include <numeric> #include <vector> #include <string> // forward declaration of get_size() method template <class T> size_t get_size(const T& obj); namespace detail { template <class T> struct get_size_helper; /** * Specialization for generic std::vector<T>, a vector is represented * in the stream by storing the number of elements (v.size()) followed * by the serialized elements (notice that we can have nested structures */ template <class T> struct get_size_helper<std::vector<T>> { static size_t value(const std::vector<T>& obj) { return std::accumulate(obj.begin(), obj.end(), sizeof(size_t), [](const size_t& acc, const T& cur) { return acc+get_size(cur); }); } }; /** * Specialization for an std::string. Similarly to the vector, we store * the number of elements of the string (str.length()), followed by the * chars. In this case we are sure the elements of the string are bytes * therefore we can compute the size without recurring */ template <> struct get_size_helper<std::string> { static size_t value(const std::string& obj) { return sizeof(size_t) + obj.length()*sizeof(uint8_t); } }; template <class tuple_type> inline size_t get_tuple_size(const tuple_type& obj, int_<0>) { constexpr size_t idx = std::tuple_size<tuple_type>::value-1; return get_size(std::get<idx>(obj)); } template <class tuple_type, size_t pos> inline size_t get_tuple_size(const tuple_type& obj, int_<pos>) { constexpr size_t idx = std::tuple_size<tuple_type>::value-pos-1; size_t acc = get_size(std::get<idx>(obj)); return acc+get_tuple_size(obj, int_<pos-1>()); } /** * specialization for std::tuple<T...>. In this case we don't need to * store the number of elements since this information is explicit * with the type itself. Therefore we simply serialize the elements * of the tuple */ template <class ...T> struct get_size_helper<std::tuple<T...>> { static size_t value(const std::tuple<T...>& obj) { return get_tuple_size(obj, int_<sizeof...(T)-1>()); } }; /** * Specialization for any remaining type, simply use the value of * sizeof() */ template <class T> struct get_size_helper { static size_t value(const T& obj) { return sizeof(T); } }; } // end detail namespace template <class T> inline size_t get_size(const T& obj) { return detail::get_size_helper<T>::value(obj); }