Correct and portable serialization So I've made custom binary streams which work like this:

/// \brief Reads a variable from the stream.
/// \tparam T Type of the variable.
/// \param[out] var Variable to read.
/// \return Reference to this stream.
/// \throw TODO
/// \note No endianness conversion will be performed if a byte is not 8 bit
/// wide.
template &lt;typename T&gt;
BinaryInputStream&amp; operator&gt;&gt;(T&amp; var)
{
    static_assert(std::is_pod&lt;T&gt;::value, "BinaryInputStream::operator&gt;&gt;: "
        "Binary stream can only read POD types.");
    static_assert(!std::is_enum&lt;T&gt;::value, "BinaryInputStream::operator&gt;&gt;: "
        "Directly reading enums is unsafe. Implement a custom overload and "
        "check the value inside it.");
    char* buffer = reinterpret_cast&lt;char*&gt;(&amp;var);
    std::size_t buffersize = sizeof(var);
    this-&gt;Read(buffer, buffersize);
#if CHAR_BIT == 8
    Endianness systemendianness = General::GetEndianness();
    if (systemendianness == Endianness::Unknown)
    {
        return *this;
    }
    if (systemendianness != this-&gt;GetEndianness())
    {
        SwapBytes(var);
    }
#endif
    return *this;
}

/// \brief Writes a variable to the stream.
/// \tparam T Type of the variable.
/// \param[in] var Variable to write.
/// \return Reference to this stream.
/// \throw TODO
/// \note No endianness conversion will be performed if a byte is not 8 bit
/// wide.
template &lt;typename T&gt;
BinaryOutputStream&amp; operator&lt;&lt;(T var)
{
    static_assert(std::is_pod&lt;T&gt;::value,
        "Binary stream can only write POD types.");
#if CHAR_BIT == 8
    Endianness systemendianness = General::GetEndianness();
    if ((systemendianness != Endianness::Unknown) &amp;&amp;
        (systemendianness != this-&gt;GetEndianness()))
    {
        SwapBytes(var);
    }
#endif
    char* buffer = reinterpret_cast&lt;char*&gt;(&amp;var);
    std::size_t buffersize = sizeof(var);
    this-&gt;Write(buffer, buffersize);
    return *this;
}

/// \brief Swaps bytes of a given variable.
/// \tparam T type of the variable.
/// \param[in,out] var Input variable.
template &lt;typename T&gt;
void SwapBytes(T &amp;var)
{
    char* buffer = reinterpret_cast&lt;char*&gt;(&amp;var);
    for (std::size_t i = 0, j = sizeof(var) - 1; i &lt; j; ++i, --j)
    {
        std::swap(buffer[i], buffer[j]);
    }
}


Is this correct? Have I triggered undefined behavior? Are static_asserts correct? Maybe they are overly restrictive or not strict enough? Please quote the standard if possible.
TODO throw documentation

Throw documentation TODO? E. g. here:

/// \throw TODO


this pointer

Usage of this as in here is unnecessary.

this-&gt;Read(buffer, buffersize);


Calling the method without it is more common.

Read(buffer, buffersize);


endiannes

Endianness systemendianness = General::GetEndianness();


I would speculate that system endianness is not going to change during runtime.

Therefore I would probably use "more constant" representation something like


static const variable
template parameter
maybe even MACRO


read &amp; swap

It doesn't look quite efficient to always read memory and swap if endiannesses don't match. What about having alternative version of Read() method already reversing the order during read?