constexpr Precalculate size of serialized data with templates and C++20 concepts 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 &lt;vector&gt;
#include &lt;cstdint&gt;
#include &lt;string&gt;
#include &lt;ranges&gt;
#include &lt;numeric&gt;
#include &lt;type_traits&gt;

#ifdef _MSC_VER // vvv MSVC implementation vvv (MSVC does not support &lt;ranges&gt; nor templates with auto arguments)

// checks the requires size of a variable
template &lt;typename T&gt;
constexpr std::size_t get_size_needed_for_type(const T&amp; value)
{
    // If the value is a bool/int/float then just get the size of it
    if constexpr (std::is_arithmetic_v&lt;T&gt;)
    {
        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&lt;T&gt; || std::is_union_v&lt;T&gt;)
    {
        // Get the size of every element
        return std::accumulate(value.cbegin(), value.cend(), std::size_t{ 0 }, [](std::size_t acc, const auto&amp; 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, &quot;Unsupported type for serialization!&quot;);
    }
}

#else // vvv GCC implementation vvv - ^^^ MSVC implementation ^^^

// Only accepts bool/int/float
template &lt;typename T&gt;
    requires std::integral&lt;T&gt; || std::floating_point&lt;T&gt;
constexpr std::size_t get_size_needed_for_type(const T&amp; 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&amp; value)
{
    // Get the size of every element
    return std::accumulate(value.cbegin(), value.cend(), std::size_t{ 0 }, [](std::size_t acc, const auto&amp; v)
    {
        return acc + get_size_needed_for_type(v);
    });
}

#endif // ^^^ GCC implementation ^^^

// Iterate through arguments, and accumulate the size of all of them
template &lt;typename... Args&gt;
constexpr std::size_t get_size_needed(const Args&amp;... args) {
  return (... + get_size_needed_for_type(args));
}

Whould be nice to get thoughts / criticism / optimization tips on this
Stick with supporting the lowest common denominator
I don't see a difference in functionality in the GCC and MSVC version of your code, so I wouldn't bother writing two implementations. That is just repeating yourself in a way.
Also note that it's not really GCC vs MSVC, it is some version of GCC and some version of MSVC that you checked, that doesn't mean all versions of those compilers have the same difference. Older versions of GCC might also not support some C++20 features that you used, and newer versions of MSVC will likely support those at some point.
Also, what about Clang, ICC and all the other compilers out there?
Use feature testing macros
If possible, use feature testing macros instead of testing for compiler brand to check whether you can use a given feature.
You can't serialize all containers by just looking at their contents
Containers can be more than just their contents. The ordered STL containers for example allow you to provide them with a functor that tells them how the elements are to be ordered. And if you go outside the STL, consider what happens if you have for example a class that implements a binary tree, and that provides begin() and end() functions to traverse the tree in-order. If you serialize just the elements, you miss the way the nodes in the tree are linked together, which might be significant information.