Guidelines Support Library Review: span<T>

The Guidelines Support Library is a Microsoft implementation of some of the types and functions described in the C++ Core Guidelines maintained by the Standard C++ Foundation. Among the types provided by the GSL is span<T> formerly known as array_view<T>. This article is an introduction to this type.

span<T> is a non-owning range of contiguous memory recommended to be used instead of pointers (and size counter) or standard containers (such as std::vector or std::array).

Suppose you want to create a function that displays the content of a container. Such a function could look like this:

This will work with vectors, but not with arrays or lists. So then you need overloads in order to support other containers.

But what if you now what to display the content of an int[] or an int*?

The span<T> type is intended as a uniform interface over arrays, pointers and standard containers that can be used as a replacement of these types. It does not store a copy of the original data, only a pointer to data and counters.

The following helper functions are used in the samples below:

Creating a span

A span can be created in many ways, including:

  • from a single value (variable, not a literal)

  • from a pointer and number of elements

  • from a begin and end pointer

  • from a C-like array

  • from a dynamic array

  • from a standard container with contiguous memory layout such as array, vector or string

  • using the gsl::as_span() function:

Notice that it is not possible to create a span from an initializer_list because an initializer list is a temporary object and a span is a non-owning container, it does not make a copy of the data, and therefore it can end up containing dangling references to temporary data. For a detailed discussion on the topic see this issue.

Size of a span

A span can have zero, one or more dimensions, and each dimension can have a different size (number of elements). The number of dimensions is called rank and the number of elements in a dimension is called extent. You can retrieve the rank and extent using the functions with the same name.

Subspans

It is possible to create subspans from a span. There are several functions that do that:

  • first(): returns the sub-span with the first N elements from the original span
  • last(): returns the sub-span with the last N elements from the original span
  • subspan(): returns the sub-span within the specified range (first and last positions) of the original span.

Comparisons

You can use the comparison operators (==, !=, <, <=, >, >=) with two spans. Equality is checked with std::equal (two ranges are equal if every element in the first range is equal to the element corresponding to the same position in the second range) and less/greater is checked with std::lexicographical_compare() (one range is less than another if the first mismatch element in the first range is less than the element on the same position in the second range).

Element access

It is possible to access the content of a span either with iterators or indexes.

When it comes to index access you can either index like a regular array (s[0], s[1][2], etc.) or using a special type called index.

3 thoughts on “Guidelines Support Library Review: span<T>

  1. Pingback: 1 – C++ Guidelines Support Library Review: Span

  2. Robert Ramey

    “span is a non-owning range of contiguous memory recommended to be used instead ”

    why “contiguous”? The only thing above which suggests the need for this requirement is that the span-view be accessible via an index. But there are lots of application which don’t call for this. So this “requirement” should be lowered to the status of “option”

    In my view – creating a new concept “span” isn’t really of much value as compared to the more traditionally used “[const] view” which has the benefit of being more intuitive. I don’t think this idea is really adding anything of value.

    Reply
  3. antonbikineev

    Thanks for the nice overview! I have one question:
    What is the reason of using const gsl::span& as a parameter? It’s a shallow type and has similar semantic as initializer_list, so I would rather prefer passing it as a value.

    Reply

Leave a Reply