Mercurial > hg > CbC > CbC_llvm
view parallel-libs/acxxel/span.h @ 206:f17a3b42b08b
Added tag before-12 for changeset b7591485f4cd
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 07 Jun 2021 21:25:57 +0900 (2021-06-07) |
parents | 1d019706d866 |
children |
line wrap: on
line source
//===--- span- The span class -----------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef ACXXEL_SPAN_H #define ACXXEL_SPAN_H #include <array> #include <cstddef> #include <exception> #include <iterator> #include <type_traits> namespace acxxel { /// Value used to indicate slicing to the end of the span. static constexpr std::ptrdiff_t dynamic_extent = -1; // NOLINT class SpanBase {}; /// Implementation of the proposed C++17 std::span class. /// /// Based on the paper: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0122r1.pdf template <typename ElementType> class Span : public SpanBase { public: /// \name constants and types /// \{ using element_type = ElementType; using index_type = std::ptrdiff_t; using pointer = element_type *; using reference = element_type &; using iterator = element_type *; using const_iterator = const element_type *; using value_type = typename std::remove_const<element_type>::type; /// \} /// \name constructors, copy, assignment, and destructor. /// \{ /// Constructs an empty span with null pointer data. Span() : Data(nullptr), Size(0) {} /// Constructs an empty span with null pointer data. // Intentionally implicit. Span(std::nullptr_t) : Data(nullptr), Size(0) {} /// Constructs a span from a pointer and element count. Span(pointer Ptr, index_type Count) : Data(Ptr), Size(Count) { if (Count < 0 || (!Ptr && Count)) std::terminate(); } /// Constructs a span from a pointer to the fist element in the range and a /// pointer to one past the last element in the range. Span(pointer FirstElem, pointer LastElem) : Data(FirstElem), Size(std::distance(FirstElem, LastElem)) { if (Size < 0) std::terminate(); } /// Constructs a span from an array. // Intentionally implicit. template <typename T, size_t N> Span(T (&Arr)[N]) : Data(Arr), Size(N) {} /// Constructs a span from a std::array. // Intentionally implicit. template <size_t N> Span(const std::array<typename std::remove_const<element_type>::type, N> &Arr) : Data(Arr.data()), Size(N) {} /// Constructs a span from a container such as a std::vector. // TODO(jhen): Put in a check to make sure this constructor does not // participate in overload resolution unless Container meets the following // requirements: // * Container is a contiguous container and a sequence container. // Intentionally implicit. template <typename Container> Span(Container &Cont, typename std::enable_if< std::is_same< typename std::remove_const<typename Container::value_type>::type, typename std::remove_const<element_type>::type>::value && !std::is_array<Container>::value && !std::is_base_of<SpanBase, Container>::value && std::is_convertible<decltype(&Cont[0]), pointer>::value>::type * = nullptr) : Data(Cont.data()), Size(Cont.size()) {} /// Avoids creating spans from expiring temporary objects. // TODO(jhen): Put in a check to make sure this constructor does not // participate in overload resolution unless Container meets the following // requirements: // * Container is a contiguous container and a sequence container. template <typename Container> Span(Container &&Cont, typename std::enable_if< std::is_same< typename std::remove_const<typename Container::value_type>::type, typename std::remove_const<element_type>::type>::value && !std::is_array<Container>::value && !std::is_base_of<SpanBase, Container>::value && std::is_convertible<decltype(&Cont[0]), pointer>::value>::type * = nullptr) = delete; Span(const Span &) noexcept = default; Span(Span &&) noexcept; /// Constructs a span from copying a span of another type that can be /// implicitly converted to the type stored by the constructed span. // Intentionally implicit. template <typename OtherElementType> Span(const Span<OtherElementType> &Other) : Data(Other.Data), Size(Other.Size) {} /// Constructs a span from moving a span of another type that can be /// implicitly converted to the type stored by the constructed span. // Intentionally implicit. template <typename OtherElementType> Span(Span<OtherElementType> &&Other) : Data(Other.Data), Size(Other.Size) {} ~Span() = default; Span &operator=(const Span &) noexcept = default; Span &operator=(Span &&) noexcept; /// \} /// \name subviews /// \{ /// Creates a span out of the first Count elements of this span. Span<element_type> first(index_type Count) const { bool Valid = Count >= 0 && Count <= size(); if (!Valid) std::terminate(); return Span<element_type>(data(), Count); } /// Creates a span out of the last Count elements of this span. Span<element_type> last(index_type Count) const { bool Valid = Count >= 0 && Count <= size(); if (!Valid) std::terminate(); return Span<element_type>(Count == 0 ? data() : data() + (size() - Count), Count); } /// Creates a span out of the Count elements of this span beginning at Offset. /// /// If no arguments is provided for Count, the new span will extend to the end /// of the current span. Span<element_type> subspan(index_type Offset, index_type Count = dynamic_extent) const { bool Valid = (Offset == 0 || (Offset > 0 && Offset <= size())) && (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())); if (!Valid) std::terminate(); return Span<element_type>( data() + Offset, Count == dynamic_extent ? size() - Offset : Count); } /// \} /// \name observers /// \{ index_type length() const { return Size; } index_type size() const { return Size; } bool empty() const { return size() == 0; } /// \} /// \name element access /// \{ reference operator[](index_type Idx) const { bool Valid = Idx >= 0 && Idx < size(); if (!Valid) std::terminate(); return Data[Idx]; } reference operator()(index_type Idx) const { return operator[](Idx); } pointer data() const noexcept { return Data; } /// \} /// \name iterator support /// \{ iterator begin() const noexcept { return Data; } iterator end() const noexcept { return Data + Size; } const_iterator cbegin() const noexcept { return Data; } const_iterator cend() const noexcept { return Data + Size; } /// \} private: template <typename OtherElementType> friend class Span; pointer Data; index_type Size; }; template <typename ElementType> Span<ElementType>::Span(Span &&) noexcept = default; template <typename ElementType> Span<ElementType> &Span<ElementType>::operator=(Span &&) noexcept = default; } // namespace acxxel #endif // ACXXEL_SPAN_H