Concept Subspace :: sus :: collections :: Join

template <class T, class Sep>
concept Join
requires(const T& t, const ::sus::num::usize& cap) {
  // The separator must be Clone to be replicated between each join.
  requires ::sus::mem::Clone<Sep>;
  // Join between types of T must report their lengths.
  { t.len() } -> std::same_as<::sus::num::usize>;
  // The Join between types of T produces this type.
  typename T::JoinOutputType;
  // The output type can be constructed with a capacity.
  } -> std::same_as<typename T::JoinOutputType>;
  requires requires(typename T::JoinOutputType& collection, const Sep& sep) {
    // The output type can be extended by each object of type T.
    { t.join_into(collection) } -> std::same_as<void>;
    // The output type can be extended by the separator `Sep`. This method is
    // static, as it does not use a specific `T`.
    { T::join_sep_into(collection, sep) } -> std::same_as<void>;

Types that support being flattened and concatenated together into a collection, with a separator between each item. This is similar to Concat but with a separator.

For example, Slice is Join<S>, which allows a Slice<Slice<U>> to be concatenated into a Slice<U> of all the original elements, with separators S cloned and placed between them. This concept requires T to provide join_into(T::JoinOutputType&) and join_sep_into(T::JoinOutputType&, const Sep&) that does the concatenation.

The join_into() method will be called with None for the first element being joined, then with Some(const Sep&) for the remaining elements.

TODO: String should satisfy Join as well.