aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2020-05-25 18:17:00 +0200
committerTim Jenssen <tim.jenssen@qt.io>2020-05-26 18:15:06 +0200
commitb3f8a4a73cfd5c12e577359ea378fa8a75955230 (patch)
tree9e08456df15cd07749ee8f3d348e852e71091994
parent9f5c1184eab0d887107ec7d9553869fbd7289c1f (diff)
Utils: Include from future std::span
std::span is a universal class to represent a non owning contiguous data. You can even manipulate the data but you can not change the size like sort. It's very nice for interfaces which call in other code but don't need to own the container or make an internal copy anyway. https: //en.cppreference.com/w/cpp/container/span https: //solarianprogrammer.com/2019/11/03/cpp-20-span-tutorial/ Change-Id: Iaced1bd60c14b2fd7ea6576bb6e1720ed8990da8 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
-rw-r--r--README.md11
-rw-r--r--doc/qtcreator/src/overview/creator-acknowledgements.qdoc15
-rw-r--r--src/libs/3rdparty/span/LICENSE_1_0.txt23
-rw-r--r--src/libs/3rdparty/span/README.md118
-rw-r--r--src/libs/3rdparty/span/span.hpp631
-rw-r--r--src/libs/utils/CMakeLists.txt2
-rw-r--r--src/libs/utils/span.h40
-rw-r--r--src/libs/utils/utils-lib.pri2
-rw-r--r--src/libs/utils/utils.qbs2
9 files changed, 844 insertions, 0 deletions
diff --git a/README.md b/README.md
index 896d2e8b71..0a4ef8a818 100644
--- a/README.md
+++ b/README.md
@@ -439,6 +439,17 @@ we thank the authors who made this possible:
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+### Implementation for std::span
+
+ https://github.com/tcbrindle/span
+
+ QtCreator/src/libs/3rdparty/span
+
+ Copyright Tristan Brindle, 2018
+
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+
### Open Source front-end for C++ (license MIT), enhanced for use in Qt Creator
Roberto Raggi <roberto.raggi@gmail.com>
diff --git a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
index bdd45fd189..0782c8ff82 100644
--- a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
+++ b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc
@@ -182,6 +182,21 @@
\li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/variant}
\endlist
+ \li \b{Implementation for std::span}
+
+ Copyright Tristan Brindle, 2018
+
+ Distributed under the \l {http://boost.org/LICENSE_1_0.txt}
+ {Boost Software License, Version 1.0}.
+ (See accompanying file LICENSE.md.)
+
+ The source code can be found here:
+ \list
+ \li \l{https://github.com/tcbrindle/span}
+ \li QtCreator/src/libs/3rdparty/span
+ \li \l{https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/libs/3rdparty/span}
+ \endlist
+
\li \b{Open Source front-end for C++ (license MIT)}, enhanced for use
in \QC.\br
Roberto Raggi <roberto.raggi@gmail.com>\br
diff --git a/src/libs/3rdparty/span/LICENSE_1_0.txt b/src/libs/3rdparty/span/LICENSE_1_0.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/src/libs/3rdparty/span/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/libs/3rdparty/span/README.md b/src/libs/3rdparty/span/README.md
new file mode 100644
index 0000000000..3601bc497d
--- /dev/null
+++ b/src/libs/3rdparty/span/README.md
@@ -0,0 +1,118 @@
+
+[![Standard](https://img.shields.io/badge/c%2B%2B-11/14/17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)
+[![License](https://img.shields.io/badge/license-BSL-blue.svg)](http://www.boost.org/LICENSE_1_0.txt)
+[![Build Status](https://travis-ci.org/tcbrindle/span.svg?branch=master)](https://travis-ci.org/tcbrindle/span)
+[![Build status](https://ci.appveyor.com/api/projects/status/ow7cj56s108fs439/branch/master?svg=true)](https://ci.appveyor.com/project/tcbrindle/span/branch/master)
+[![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/-vlZZR)
+
+`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](https://github.com/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](https://en.cppreference.com/w/cpp/container/span).
+
+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:
+
+```cpp
+// 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:
+
+ ```cpp
+ 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](https://github.com/Microsoft/GSL): The original `span` reference
+ implementation from which `std::span` was born.
+
+* [martinmoene/span_lite](https://github.com/martinmoene/span-lite): An
+ alternative implementation which offers C++98 compatibility.
+
diff --git a/src/libs/3rdparty/span/span.hpp b/src/libs/3rdparty/span/span.hpp
new file mode 100644
index 0000000000..a8414ab6fe
--- /dev/null
+++ b/src/libs/3rdparty/span/span.hpp
@@ -0,0 +1,631 @@
+
+/*
+This is an implementation of C++20's std::span
+http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
+*/
+
+// Copyright Tristan Brindle 2018.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file ../../LICENSE_1_0.txt or copy at
+// https://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef TCB_SPAN_HPP_INCLUDED
+#define TCB_SPAN_HPP_INCLUDED
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#ifndef TCB_SPAN_NO_EXCEPTIONS
+// Attempt to discover whether we're being compiled with exception support
+#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
+#define TCB_SPAN_NO_EXCEPTIONS
+#endif
+#endif
+
+#ifndef TCB_SPAN_NO_EXCEPTIONS
+#include <cstdio>
+#include <stdexcept>
+#endif
+
+// Various feature test macros
+
+#ifndef TCB_SPAN_NAMESPACE_NAME
+#define TCB_SPAN_NAMESPACE_NAME tcb
+#endif
+
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+#define TCB_SPAN_HAVE_CPP17
+#endif
+
+#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
+#define TCB_SPAN_HAVE_CPP14
+#endif
+
+namespace TCB_SPAN_NAMESPACE_NAME {
+
+// Establish default contract checking behavior
+#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
+ !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
+ !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
+#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
+#define TCB_SPAN_NO_CONTRACT_CHECKING
+#else
+#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
+#endif
+#endif
+
+#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
+struct contract_violation_error : std::logic_error {
+ explicit contract_violation_error(const char* msg) : std::logic_error(msg)
+ {}
+};
+
+inline void contract_violation(const char* msg)
+{
+ throw contract_violation_error(msg);
+}
+
+#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
+[[noreturn]] inline void contract_violation(const char* /*unused*/)
+{
+ std::terminate();
+}
+#endif
+
+#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
+#define TCB_SPAN_STRINGIFY(cond) #cond
+#define TCB_SPAN_EXPECT(cond) \
+ cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
+#else
+#define TCB_SPAN_EXPECT(cond)
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
+#define TCB_SPAN_INLINE_VAR inline
+#else
+#define TCB_SPAN_INLINE_VAR
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP14) || \
+ (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
+#define TCB_SPAN_HAVE_CPP14_CONSTEXPR
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
+#define TCB_SPAN_CONSTEXPR14 constexpr
+#else
+#define TCB_SPAN_CONSTEXPR14
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && \
+ (!defined(_MSC_VER) || _MSC_VER > 1900)
+#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
+#else
+#define TCB_SPAN_CONSTEXPR_ASSIGN
+#endif
+
+#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
+#define TCB_SPAN_CONSTEXPR11 constexpr
+#else
+#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
+#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
+#define TCB_SPAN_HAVE_STD_BYTE
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
+#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
+#endif
+
+#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
+#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
+#else
+#define TCB_SPAN_ARRAY_CONSTEXPR
+#endif
+
+#ifdef TCB_SPAN_HAVE_STD_BYTE
+using byte = std::byte;
+#else
+using byte = unsigned char;
+#endif
+
+#if defined(TCB_SPAN_HAVE_CPP17)
+#define TCB_SPAN_NODISCARD [[nodiscard]]
+#else
+#define TCB_SPAN_NODISCARD
+#endif
+
+TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX;
+
+template <typename ElementType, std::size_t Extent = dynamic_extent>
+class span;
+
+namespace detail {
+
+template <typename E, std::size_t S>
+struct span_storage {
+ constexpr span_storage() noexcept = default;
+
+ constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
+ : ptr(p_ptr)
+ {}
+
+ E* ptr = nullptr;
+ static constexpr std::size_t size = S;
+};
+
+template <typename E>
+struct span_storage<E, dynamic_extent> {
+ constexpr span_storage() noexcept = default;
+
+ constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
+ : ptr(p_ptr), size(p_size)
+ {}
+
+ E* ptr = nullptr;
+ std::size_t size = 0;
+};
+
+// Reimplementation of C++17 std::size() and std::data()
+#if defined(TCB_SPAN_HAVE_CPP17) || \
+ defined(__cpp_lib_nonmember_container_access)
+using std::data;
+using std::size;
+#else
+template <class C>
+constexpr auto size(const C& c) -> decltype(c.size())
+{
+ return c.size();
+}
+
+template <class T, std::size_t N>
+constexpr std::size_t size(const T (&)[N]) noexcept
+{
+ return N;
+}
+
+template <class C>
+constexpr auto data(C& c) -> decltype(c.data())
+{
+ return c.data();
+}
+
+template <class C>
+constexpr auto data(const C& c) -> decltype(c.data())
+{
+ return c.data();
+}
+
+template <class T, std::size_t N>
+constexpr T* data(T (&array)[N]) noexcept
+{
+ return array;
+}
+
+template <class E>
+constexpr const E* data(std::initializer_list<E> il) noexcept
+{
+ return il.begin();
+}
+#endif // TCB_SPAN_HAVE_CPP17
+
+#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
+using std::void_t;
+#else
+template <typename...>
+using void_t = void;
+#endif
+
+template <typename T>
+using uncvref_t =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+template <typename>
+struct is_span : std::false_type {};
+
+template <typename T, std::size_t S>
+struct is_span<span<T, S>> : std::true_type {};
+
+template <typename>
+struct is_std_array : std::false_type {};
+
+template <typename T, std::size_t N>
+struct is_std_array<std::array<T, N>> : std::true_type {};
+
+template <typename, typename = void>
+struct has_size_and_data : std::false_type {};
+
+template <typename T>
+struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
+ decltype(detail::data(std::declval<T>()))>>
+ : std::true_type {};
+
+template <typename C, typename U = uncvref_t<C>>
+struct is_container {
+ static constexpr bool value =
+ !is_span<U>::value && !is_std_array<U>::value &&
+ !std::is_array<U>::value && has_size_and_data<C>::value;
+};
+
+template <typename T>
+using remove_pointer_t = typename std::remove_pointer<T>::type;
+
+template <typename, typename, typename = void>
+struct is_container_element_type_compatible : std::false_type {};
+
+template <typename T, typename E>
+struct is_container_element_type_compatible<
+ T, E,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_cv<decltype(
+ detail::data(std::declval<T>()))>::type,
+ void>::value>::type>
+ : std::is_convertible<
+ remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
+ E (*)[]> {};
+
+template <typename, typename = size_t>
+struct is_complete : std::false_type {};
+
+template <typename T>
+struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
+
+} // namespace detail
+
+template <typename ElementType, std::size_t Extent>
+class span {
+ static_assert(std::is_object<ElementType>::value,
+ "A span's ElementType must be an object type (not a "
+ "reference type or void)");
+ static_assert(detail::is_complete<ElementType>::value,
+ "A span's ElementType must be a complete type (not a forward "
+ "declaration)");
+ static_assert(!std::is_abstract<ElementType>::value,
+ "A span's ElementType cannot be an abstract class type");
+
+ using storage_type = detail::span_storage<ElementType, Extent>;
+
+public:
+ // constants and types
+ using element_type = ElementType;
+ using value_type = typename std::remove_cv<ElementType>::type;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = element_type*;
+ using const_pointer = const element_type*;
+ using reference = element_type&;
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ static constexpr size_type extent = Extent;
+
+ // [span.cons], span constructors, copy, assignment, and destructor
+ template <
+ std::size_t E = Extent,
+ typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
+ constexpr span() noexcept
+ {}
+
+ TCB_SPAN_CONSTEXPR11 span(pointer ptr, size_type count)
+ : storage_(ptr, count)
+ {
+ TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
+ }
+
+ TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
+ : storage_(first_elem, last_elem - first_elem)
+ {
+ TCB_SPAN_EXPECT(extent == dynamic_extent ||
+ last_elem - first_elem ==
+ static_cast<std::ptrdiff_t>(extent));
+ }
+
+ template <std::size_t N, std::size_t E = Extent,
+ typename std::enable_if<
+ (E == dynamic_extent || N == E) &&
+ detail::is_container_element_type_compatible<
+ element_type (&)[N], ElementType>::value,
+ int>::type = 0>
+ constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
+ {}
+
+ template <std::size_t N, std::size_t E = Extent,
+ typename std::enable_if<
+ (E == dynamic_extent || N == E) &&
+ detail::is_container_element_type_compatible<
+ std::array<value_type, N>&, ElementType>::value,
+ int>::type = 0>
+ TCB_SPAN_ARRAY_CONSTEXPR span(std::array<value_type, N>& arr) noexcept
+ : storage_(arr.data(), N)
+ {}
+
+ template <std::size_t N, std::size_t E = Extent,
+ typename std::enable_if<
+ (E == dynamic_extent || N == E) &&
+ detail::is_container_element_type_compatible<
+ const std::array<value_type, N>&, ElementType>::value,
+ int>::type = 0>
+ TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<value_type, N>& arr) noexcept
+ : storage_(arr.data(), N)
+ {}
+
+ template <
+ typename Container, std::size_t E = Extent,
+ typename std::enable_if<
+ E == dynamic_extent && detail::is_container<Container>::value &&
+ detail::is_container_element_type_compatible<
+ Container&, ElementType>::value,
+ int>::type = 0>
+ constexpr span(Container& cont)
+ : storage_(detail::data(cont), detail::size(cont))
+ {}
+
+ template <
+ typename Container, std::size_t E = Extent,
+ typename std::enable_if<
+ E == dynamic_extent && detail::is_container<Container>::value &&
+ detail::is_container_element_type_compatible<
+ const Container&, ElementType>::value,
+ int>::type = 0>
+ constexpr span(const Container& cont)
+ : storage_(detail::data(cont), detail::size(cont))
+ {}
+
+ constexpr span(const span& other) noexcept = default;
+
+ template <typename OtherElementType, std::size_t OtherExtent,
+ typename std::enable_if<
+ (Extent == OtherExtent || Extent == dynamic_extent) &&
+ std::is_convertible<OtherElementType (*)[],
+ ElementType (*)[]>::value,
+ int>::type = 0>
+ constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
+ : storage_(other.data(), other.size())
+ {}
+
+ ~span() noexcept = default;
+
+ TCB_SPAN_CONSTEXPR_ASSIGN span&
+ operator=(const span& other) noexcept = default;
+
+ // [span.sub], span subviews
+ template <std::size_t Count>
+ TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const
+ {
+ TCB_SPAN_EXPECT(Count <= size());
+ return {data(), Count};
+ }
+
+ template <std::size_t Count>
+ TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const
+ {
+ TCB_SPAN_EXPECT(Count <= size());
+ return {data() + (size() - Count), Count};
+ }
+
+ template <std::size_t Offset, std::size_t Count = dynamic_extent>
+ using subspan_return_t =
+ span<ElementType, Count != dynamic_extent
+ ? Count
+ : (Extent != dynamic_extent ? Extent - Offset
+ : dynamic_extent)>;
+
+ template <std::size_t Offset, std::size_t Count = dynamic_extent>
+ TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
+ {
+ TCB_SPAN_EXPECT(Offset <= size() &&
+ (Count == dynamic_extent || Offset + Count <= size()));
+ return {data() + Offset,
+ Count != dynamic_extent ? Count : size() - Offset};
+ }
+
+ TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
+ first(size_type count) const
+ {
+ TCB_SPAN_EXPECT(count <= size());
+ return {data(), count};
+ }
+
+ TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
+ last(size_type count) const
+ {
+ TCB_SPAN_EXPECT(count <= size());
+ return {data() + (size() - count), count};
+ }
+
+ TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
+ subspan(size_type offset, size_type count = dynamic_extent) const
+ {
+ TCB_SPAN_EXPECT(offset <= size() &&
+ (count == dynamic_extent || offset + count <= size()));
+ return {data() + offset,
+ count == dynamic_extent ? size() - offset : count};
+ }
+
+ // [span.obs], span observers
+ constexpr size_type size() const noexcept { return storage_.size; }
+
+ constexpr size_type size_bytes() const noexcept
+ {
+ return size() * sizeof(element_type);
+ }
+
+ TCB_SPAN_NODISCARD constexpr bool empty() const noexcept
+ {
+ return size() == 0;
+ }
+
+ // [span.elem], span element access
+ TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
+ {
+ TCB_SPAN_EXPECT(idx < size());
+ return *(data() + idx);
+ }
+
+ TCB_SPAN_CONSTEXPR11 reference front() const
+ {
+ TCB_SPAN_EXPECT(!empty());
+ return *data();
+ }
+
+ TCB_SPAN_CONSTEXPR11 reference back() const
+ {
+ TCB_SPAN_EXPECT(!empty());
+ return *(data() + (size() - 1));
+ }
+
+ constexpr pointer data() const noexcept { return storage_.ptr; }
+
+ // [span.iterators], span iterator support
+ constexpr iterator begin() const noexcept { return data(); }
+
+ constexpr iterator end() const noexcept { return data() + size(); }
+
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
+ {
+ return reverse_iterator(end());
+ }
+
+ TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
+ {
+ return reverse_iterator(begin());
+ }
+
+ TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crbegin() const noexcept
+ {
+ return const_reverse_iterator(cend());
+ }
+
+ TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crend() const noexcept
+ {
+ return const_reverse_iterator(cbegin());
+ }
+
+ friend constexpr iterator begin(span s) noexcept { return s.begin(); }
+
+ friend constexpr iterator end(span s) noexcept { return s.end(); }
+
+private:
+ storage_type storage_{};
+};
+
+#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
+
+/* Deduction Guides */
+template <class T, size_t N>
+span(T (&)[N])->span<T, N>;
+
+template <class T, size_t N>
+span(std::array<T, N>&)->span<T, N>;
+
+template <class T, size_t N>
+span(const std::array<T, N>&)->span<const T, N>;
+
+template <class Container>
+span(Container&)->span<typename Container::value_type>;
+
+template <class Container>
+span(const Container&)->span<const typename Container::value_type>;
+
+#endif // TCB_HAVE_DEDUCTION_GUIDES
+
+template <typename ElementType, std::size_t Extent>
+constexpr span<ElementType, Extent>
+make_span(span<ElementType, Extent> s) noexcept
+{
+ return s;
+}
+
+template <typename T, std::size_t N>
+constexpr span<T, N> make_span(T (&arr)[N]) noexcept
+{
+ return {arr};
+}
+
+template <typename T, std::size_t N>
+TCB_SPAN_ARRAY_CONSTEXPR span<T, N> make_span(std::array<T, N>& arr) noexcept
+{
+ return {arr};
+}
+
+template <typename T, std::size_t N>
+TCB_SPAN_ARRAY_CONSTEXPR span<const T, N>
+make_span(const std::array<T, N>& arr) noexcept
+{
+ return {arr};
+}
+
+template <typename Container>
+constexpr span<typename Container::value_type> make_span(Container& cont)
+{
+ return {cont};
+}
+
+template <typename Container>
+constexpr span<const typename Container::value_type>
+make_span(const Container& cont)
+{
+ return {cont};
+}
+
+template <typename ElementType, std::size_t Extent>
+span<const byte, ((Extent == dynamic_extent) ? dynamic_extent
+ : sizeof(ElementType) * Extent)>
+as_bytes(span<ElementType, Extent> s) noexcept
+{
+ return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
+}
+
+template <
+ class ElementType, size_t Extent,
+ typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
+span<byte, ((Extent == dynamic_extent) ? dynamic_extent
+ : sizeof(ElementType) * Extent)>
+as_writable_bytes(span<ElementType, Extent> s) noexcept
+{
+ return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
+}
+
+template <std::size_t N, typename E, std::size_t S>
+constexpr auto get(span<E, S> s) -> decltype(s[N])
+{
+ return s[N];
+}
+
+} // namespace TCB_SPAN_NAMESPACE_NAME
+
+namespace std {
+
+template <typename ElementType, size_t Extent>
+class tuple_size<TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>>
+ : public integral_constant<size_t, Extent> {};
+
+template <typename ElementType>
+class tuple_size<TCB_SPAN_NAMESPACE_NAME::span<
+ ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not defined
+
+template <size_t I, typename ElementType, size_t Extent>
+class tuple_element<I, TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>> {
+public:
+ static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent &&
+ I < Extent,
+ "");
+ using type = ElementType;
+};
+
+} // end namespace std
+
+#endif // TCB_SPAN_HPP_INCLUDED
diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt
index ff7bbe6286..21512ca682 100644
--- a/src/libs/utils/CMakeLists.txt
+++ b/src/libs/utils/CMakeLists.txt
@@ -6,6 +6,7 @@ add_qtc_library(Utils
SOURCES
../3rdparty/optional/optional.hpp
../3rdparty/variant/variant.hpp
+ ../3rdparty/span/span.hpp
QtConcurrentTools
algorithm.h
ansiescapecodehandler.cpp ansiescapecodehandler.h
@@ -135,6 +136,7 @@ add_qtc_library(Utils
smallstringmemory.h
smallstringvector.h
smallstringview.h
+ span.h
statuslabel.cpp statuslabel.h
stringutils.cpp stringutils.h
styledbar.cpp styledbar.h
diff --git a/src/libs/utils/span.h b/src/libs/utils/span.h
new file mode 100644
index 0000000000..6b0055dff2
--- /dev/null
+++ b/src/libs/utils/span.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#if __cplusplus >= 202002L
+#include <span>
+
+namespace Utils {
+using std::as_bytes;
+using std::as_writable_bytes;
+using std::get;
+using std::span;
+} // namespace Utils
+#else
+#define TCB_SPAN_NAMESPACE_NAME Utils
+#include <3rdparty/span/span.hpp>
+#endif
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 55dd718a72..bc5c36e5fe 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -150,6 +150,8 @@ HEADERS += \
$$PWD/pointeralgorithm.h \
$$PWD/qrcparser.h \
$$PWD/qtcprocess.h \
+ $$PWD/span.h \
+ $$PWD/../3rdparty/span/span.hpp \
$$PWD/utils_global.h \
$$PWD/reloadpromptutils.h \
$$PWD/settingsaccessor.h \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index ed15c78d8e..e7e862da23 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -241,6 +241,8 @@ Project {
"smallstringlayout.h",
"smallstringmemory.h",
"smallstringvector.h",
+ "span.h",
+ "../3rdparty/span/span.hpp",
"statuslabel.cpp",
"statuslabel.h",
"stringutils.cpp",