Concept Subspace :: sus :: construct :: Into

template <class FromType, class ToType>
concept Into
requires
::sus::construct::From<ToType, FromType> || std::same_as<ToType, FromType>

A concept that declares FromType can be converted to ToType.

When true, the conversion can be done in one of three ways:

  • ToType::from(FromType) can be used to construct ToType, which is the preferred way to write conversions. It avoids any accidental conversions as it does not have an ambiguous appearance with a copy or move.
  • ToType is the same as FromType, in which case a reference to the object is passed along, and no construction or conversion happens.

This is the inverse direction from the From concept, while also a broader generalization. It is meant to be used on methods that want to receive any type that can explicitly be converted to a specific type.

This concept is not implementable directly, as it's satisfied for T by implementing the From<T> concept on a different type. It is only possible to satisfy this concept for a ToType that is not a reference, as it needs to be able to construct ToType.

Templates

To receive into() correctly for a templated function argument:

  • Avoid std::same_as<T>, use std::convertible_to<T> instead, as this will accept the marker type returned from into.
  • If the argument is a fixed dependent type, like the following:
    template <class T, class In = Foo<T>>
    void f(In i) {}
    
    Insert an extra template parameter that uses std::convertible_to and the template type, such as:
    template <class T, class Exact = Foo<T>, std::convertible_to<Exact> In>
    void f(In i) {}
    
    As this will allow receiving types converted to Exact by the caller using into.

Arrays

Receiving an array is possible by implementing From with from() being a templated method templated on a size_t template parameter which represents the size of the incoming array. For example:

// sus::construct::Into<Slice<T>, T[N]> trait.
template <size_t N>
static constexpr Slice from(T (&data)[N]) noexcept {
  return Slice(data, N);
}

Then sus::into(an_array) can be used to construct Slice<T>.