Im writing a serializer that will do serialization/deserialization as fast as possible, and that uses templates so that i dont have to create a ton of functions for every data structure,
This is the part of it that pre-calculates the size of the data to be serialized
I have only tested this on MSVC and GCC
So this code has get_size_needed() which should get the total size (in bytes) needed to store the data for the arguments.
You should be able to put any container/arithmetic type (and any combination of those types) into it as a argument and it should calculate its size at compile time.
It should also support calculating the size of nested containers.
sorry if its messy, this is my first time dealing with templates and concepts (with some help from some people)
Serialization.h
#include <vector> #include <cstdint> #include <string> #include <ranges> #include <numeric> #include <type_traits> #ifdef _MSC_VER // vvv MSVC implementation vvv (MSVC does not support <ranges> nor templates with auto arguments) // checks the requires size of a variable template <typename T> constexpr std::size_t get_size_needed_for_type(const T& value) { // If the value is a bool/int/float then just get the size of it if constexpr (std::is_arithmetic_v<T>) { return sizeof(value); } // If the value is a container, then get the size of the container, and the size of its elements else if constexpr (std::is_class_v<T> || std::is_union_v<T>) { // Get the size of every element return std::accumulate(value.cbegin(), value.cend(), std::size_t{ 0 }, [](std::size_t acc, const auto& v) { return acc + get_size_needed_for_type(v); }); } // I dont know what whould end up here, but its probably not something thats serializable else { static_assert(false, "Unsupported type for serialization!"); } } #else // vvv GCC implementation vvv - ^^^ MSVC implementation ^^^ // Only accepts bool/int/float template <typename T> requires std::integral<T> || std::floating_point<T> constexpr std::size_t get_size_needed_for_type(const T& value) { return sizeof(value); // return the size of it } // If the is a range, then its probably a container, then get the size of the container, and the size of its elements constexpr std::size_t get_size_needed_for_type(const std::ranges::range auto& value) { // Get the size of every element return std::accumulate(value.cbegin(), value.cend(), std::size_t{ 0 }, [](std::size_t acc, const auto& v) { return acc + get_size_needed_for_type(v); }); } #endif // ^^^ GCC implementation ^^^ // Iterate through arguments, and accumulate the size of all of them template <typename... Args> constexpr std::size_t get_size_needed(const Args&... args) { return (... + get_size_needed_for_type(args)); } Whould be nice to get thoughts / criticism / optimization tips on this