Home > Mobile >  How to make class compatible with std::span constructor that takes a range?
How to make class compatible with std::span constructor that takes a range?

Time:09-23

I'd like to be able to pass my custom container this std::span constructor:

template< class R >
explicit(extent != std::dynamic_extent)
constexpr span( R&& range );

What do I need to add to my custom class to make it satisfy the requirements to be able to pass it to the std::span constructor that receives a range?

For example, with std::vector we are able to do this:

std::vector<int> v = {1, 2, 3};
auto span = std::span{v};

I've already added these to my custom class:

Type* begin()
{
    return m_Data;
}

Type* end()
{
    return m_Data   m_Length;
}

const Type* data() const
{
    return m_Data;
}

size_t size() const
{
    return m_Length;
}

...which in turn allowed me to use range-based loops, and std::data(my_container) as well as std::size(my_container). What am I missing to make it so that I can also pass my container to the std::span constructor? Does it require to implement a more complex iterator?

CodePudding user response:

This is because your Container does not satisfy contiguous_range, which is defined as:

template<class T>
  concept contiguous_­range =
    random_­access_­range<T> && contiguous_­iterator<iterator_t<T>> &&
    requires(T& t) {
      { ranges::data(t) } -> same_­as<add_pointer_t<range_reference_t<T>>>;
    };

In the requires clause, the return type of ranges::data(t) is const Type*, which is different from add_pointer_t<range_reference_t<T>> that is Type*.

The workaround is adding a non-const data() to your Container which return Type*:

Type* data()  { return m_Data; }
  • Related