HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

GSL-like array_view implementation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementationgsllikearray_view

Problem

I've seen a couple GSL-like string_view-ish implementations on CR recently, but don't recall seeing anything like array_view yet (AKA span in the GSL), so I wrote one just for fun!

My implementation is a simplified array_view that doesn't support the bounds and indexing in the same way the GSL span does. I also didn't add support for multidimensional arrays, data is always assumed to be a flat 1D array. Here's the documentation for a complete array_view class that might some day make into the Standard library.

```
#include
#include
#include
#include
#include
#include
#include

namespace cr
{

template
class array_view final
{
public:

//
// Nested types:
//

using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

using pointer = std::add_pointer_t;
using reference = std::add_lvalue_reference_t;
using const_pointer = std::add_pointer_t;
using const_reference = std::add_lvalue_reference_t;

using iterator = array_iterator_base;
using const_iterator = array_iterator_base;
using reverse_iterator = std::reverse_iterator;
using const_reverse_iterator = std::reverse_iterator;

//
// Constructors / assignment:
//

constexpr array_view() noexcept
: m_pointer{ nullptr }
, m_size_in_items{ 0 }
{ }

template
constexpr explicit array_view(ArrayType (&arr)[ArraySize]) noexcept
: m_pointer{ arr }
, m_size_in_items{ ArraySize }
{ }

template
constexpr explicit array_view(ContainerType & container) noexcept
: m_pointer{ container.data() }
, m_size_in_items{ container.size() }
{ }

template
constexpr array_view(ConvertibleType * array_ptr, const size_type size_in_items) noexcept
: m_pointer{ array_ptr }
, m_size_in_items{ size_in_items }
{ }

tem

Solution

Implementation

  • if(slice_ptr > end_ptr) inside array_view::slice(const size_type, const size_type) might invoke undefined behavior (it's undefined if the condition would return true and the original allocation of the underlying contiguous memory ends at end_ptr). However, it could easily be replaced with the logically equivalent if(start_offset > size()). Also, the comparison should be >= instead of >, as end_ptr already points 1 past the last covered element, so starting a non-empty array slice there isn't possible.



  • if (slice_size > (size() - start_offset)) in the same function could be combined with the check above to if (end_offset



  • The comparison operators invoke undefined behavior unless both array_views are slices of the same underlying array. This could be fixed by using std::less (or corresponding equivalents) to do the comparison, but what would be a use case of comparing the addresses of the two arrays relatively to each other?



Template restrictions

  • array_view::value_type should probably be restricted to std::remove_reference, as there can not be an array of references.



  • ArrayType (of the array_view constructor) can only ever legally be the same as array_view::value_type, so this template parameter is not necessary. With the lack of proper restrictions, it would allow to assign an array of objects derived from array_view::value_type, which cannot be indexed correctly (m_pointer[1] might not point to the address of arr[1] if sizeof(array_view::value_type)



  • I don't think ConvertibleType (see the two constructors and the assignment operator) is treated correctly either:



  • If ConvertibleType is derived from array_view::value_type, the same problem as with ArrayType above occurs.



  • If ConvertibleType is has a conversion operator to array_view::value_type, the pointer cannot be correctly assigned to m_pointer legally (only legal for array_view::pointer or derived types).

Context

StackExchange Code Review Q#117508, answer score: 3

Revisions (0)

No revisions yet.