Repository: bitcoin/bitcoin
File: src/serialize.h (C/C++)

Code before:
 */
template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);

/**
 * set
 */
template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);

/**
 * shared_ptr
 */
template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);

/**
 * unique_ptr
 */
template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);



/**
 * If none of the specialized versions above matched, default to calling member function.
 */
template<typename Stream, typename T>
inline void Serialize(Stream& os, const T& a)
{
    a.Serialize(os);
}

template<typename Stream, typename T>
inline void Unserialize(Stream& is, T&& a)
{
    a.Unserialize(is);
}

/** Default formatter. Serializes objects as themselves.
 *
 * The vector/prevector serialization code passes this to VectorFormatter
 * to enable reusing that logic. It shouldn't be needed elsewhere.
 */
struct DefaultFormatter
{
    template<typename Stream, typename T>
    static void Ser(Stream& s, const T& t) { Serialize(s, t); }

    template<typename Stream, typename T>
    static void Unser(Stream& s, T& t) { Unserialize(s, t); }

Review comment (suggestion):
Could consider:

```c++
template <class Stream>
concept WritableStream = requires(Stream& s, const Span<std::byte> src) { s.write(src); };

template <class T, class Stream>
concept Serializable = WritableStream<Stream> && requires(T a, Stream s) { a.Serialize(s); };

template <class Stream>
concept ReadableStream = requires(Stream& s, Span<std::byte> dst) { s.read(dst); };

template <class T, class Stream>
concept Unserializable = ReadableStream<Stream> && requires(T a, Stream s) { a.Unserialize(s); };
```

Code after:
template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);

/**
 * set
 */
template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);

/**
 * shared_ptr
 */
template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);

/**
 * unique_ptr
 */
template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);


/**
 * If none of the specialized versions above matched, default to calling member function.
 */
template <class T, class Stream>
concept Serializable = requires(T a, Stream s) { a.Serialize(s); };
template <typename Stream, typename T>
    requires Serializable<T, Stream>
void Serialize(Stream& os, const T& a)
{
    a.Serialize(os);
}

template <class T, class Stream>
concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };
template <typename Stream, typename T>
    requires Unserializable<T, Stream>
void Unserialize(Stream& is, T&& a)
{
    a.Unserialize(is);
}

/** Default formatter. Serializes objects as themselves.
 *
 * The vector/prevector serialization code passes this to VectorFormatter
 * to enable reusing that logic. It shouldn't be needed elsewhere.
 */
struct DefaultFormatter
{
    template<typename Stream, typename T>
    static void Ser(Stream& s, const T& t) { Serialize(s, t); }