• Stars
    star
    326
  • Rank 129,027 (Top 3 %)
  • Language
    C++
  • License
    Boost Software Li...
  • Created over 6 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Implementation of C++20's std::span for older compilers

Standard License Build Status Build status Try it on godbolt online

std::span implementation for C++11 and later

This repository contains a single-header implementation of C++20's std::span, conforming to the C++20 committee draft. It is compatible with C++11, but will use newer language features if they are available.

It differs from the implementation in the Microsoft GSL in that it is single-header and does not depend on any other GSL facilities. It also works with C++11, while the GSL version requires C++14.

Usage

The recommended way to use the implementation simply copy the file span.hpp from include/tcb/ into your own sources and #include it like any other header. By default, it lives in namespace tcb, but this can be customised by setting the macro TCB_SPAN_NAMESPACE_NAME to an appropriate string before #include-ing the header -- or simply edit the source code.

The rest of the repository contains testing machinery, and is not required for use.

Compatibility

This implementation requires a conforming C++11 (or later) compiler, and is tested as far back as GCC 5, Clang 3.5 and MSVC 2015 Update 3. Older compilers may work, but this is not guaranteed.

Documentation

Documentation for std::span is available on cppreference.

Implementation Notes

Bounds Checking

This implementation of span includes optional bounds checking, which is handled either by throwing an exception or by calling std::terminate().

The default behaviour with C++14 and later is to check the macro NDEBUG: if this is set, bounds checking is disabled. Otherwise, std::terminate() will be called if there is a precondition violation (i.e. the same behaviour as assert()). If you wish to terminate on errors even if NDEBUG is set, define the symbol TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION before #include-ing the header.

Alternatively, if you want to throw on a contract violation, define TCB_SPAN_THROW_ON_CONTRACT_VIOLATION. This will throw an exception of an implementation-defined type (deriving from std::logic_error), allowing cleanup to happen. Note that defining this symbol will cause the checks to be run even if NDEBUG is set.

Lastly, if you wish to disable contract checking even in debug builds, #define TCB_SPAN_NO_CONTRACT_CHECKING.

Under C++11, due to the restrictions on constexpr functions, contract checking is disabled by default even if NDEBUG is not set. You can change this by defining either of the above symbols, but this will result in most of span's interface becoming non-constexpr.

constexpr

This implementation is fully constexpr under C++17 and later. Under earlier versions, it is "as constexpr as possible".

Note that even in C++17, it is generally not possible to declare a span as non-default constructed constexpr variable, for the same reason that you cannot form a constexpr pointer to a value: it involves taking the address of a compile-time variable in a way that would be visible at run-time. You can however use a span freely in a constexpr function. For example:

// Okay, even in C++11
constexpr std::ptrdiff_t get_span_size(span<const int> span)
{
    return span.size();
}

constexpr int arr[] = {1, 2, 3};
constexpr auto size = get_span_size(arr); // Okay
constexpr span<const int> span{arr}; // ERROR -- not a constant expression
constexpr const int* p = arr; // ERROR -- same

Constructor deduction guides are provided if the compiler supports them. For older compilers, a set of make_span() functions are provided as an extension which use the same logic, for example:

constexpr int c_array[] = {1, 2, 3};
std::array<int, 3> std_array{1, 2, 3};
const std::vector<int> vec{1, 2, 3};

auto s1 = make_span(c_array);   // returns span<const int, 3>
auto s2 = make_span(std_array); // returns span<int, 3>
auto s3 = make_span(vec);       // returns span<const int, dynamic_extent>

Alternatives

  • Microsoft/GSL: The original span reference implementation from which std::span was born.

  • martinmoene/span_lite: An alternative implementation which offers C++98 compatibility.

More Repositories

1

raytracer.hpp

Simple compile-time raytracer using C++17
C
688
star
2

flux

A C++20 library for sequence-orientated programming
C++
474
star
3

NanoRange

Range-based goodness for C++17
C++
357
star
4

sdl2-cmake-scripts

CMake scripts for finding SDL2 headers and libraries on multiple platforms
CMake
325
star
5

cpp17_headers

C++17 library facilities for older compilers
C++
145
star
6

libflow

C++
62
star
7

numeris_romanis

Roman numeral support for C++17
C++
51
star
8

utf_ranges

A collection of Unicode utilities for C++ using Range-V3
C++
43
star
9

numeric_ranges

Numeric algorithms for C++20 Ranges
C++
30
star
10

gsound

GObject wrapper for libcanberra
C
13
star
11

rational

Single-header rational number library for C++14
C++
12
star
12

thinmatrix-gl-tutorials

C
10
star
13

systemd-glib

GObject bindings for the systemd D-Bus API
Vala
6
star
14

gvs

Work-in-progress GObject to GVariant serialization library
C
6
star
15

pretty_print.hpp

Single-header pretty-printing library for STL-compatible containers
C++
6
star
16

advent_of_code_2023

C++
6
star
17

modern-io

Modern IO library for C++
C++
5
star
18

leftpad

Of course I'm serious
C++
4
star
19

advent_of_code_2018

C++17/20 solutions for 2018's Advent of Code
C++
4
star
20

unicode.hpp

Unicode utilities for C++
C++
3
star
21

advent_of_code_2022

C++
3
star
22

sdlxx

Modern C++ binding for SDL2
C++
3
star
23

libsudoku

C and C++14 library for solving sudoku puzzles, using Range-V3
C++
2
star
24

advent_of_code_2020

C++
2
star
25

advent_of_code_2021

C++
1
star
26

wg21papertemplate

A LaTeX template for ISO C++ committee (aka WG21) papers.
TeX
1
star
27

variant

Clone of https://bitbucket.org/anthonyw/variant
C++
1
star