blob: 38cf9f50e59bc2fc7ff41f549f0b7efef77128f6 [file] [log] [blame]
Neil MacIntoshcec26a22016-02-24 11:26:28 -08001///////////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
4//
5// This code is licensed under the MIT License (MIT).
6//
7// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
12// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
13// THE SOFTWARE.
14//
15///////////////////////////////////////////////////////////////////////////////
16
17#pragma once
18
19#ifndef GSL_SPAN_H
20#define GSL_SPAN_H
21
22#include "gsl_assert.h"
23#include "gsl_util.h"
Neil MacIntoshcec26a22016-02-24 11:26:28 -080024#include <array>
Neil MacIntoshcec26a22016-02-24 11:26:28 -080025#include <limits>
Neil MacIntoshd3929c52016-02-24 16:11:33 -080026#include <iterator>
Neil MacIntoshcec26a22016-02-24 11:26:28 -080027#include <stdexcept>
28#include <type_traits>
29#include <utility>
30
31#ifdef _MSC_VER
32
33// turn off some warnings that are noisy about our Expects statements
34#pragma warning(push)
35#pragma warning(disable : 4127) // conditional expression is constant
36
37// No MSVC does constexpr fully yet
38#pragma push_macro("constexpr")
39#define constexpr
40
41// VS 2013 workarounds
42#if _MSC_VER <= 1800
43
44#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
45#define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
46
47// noexcept is not understood
48#ifndef GSL_THROW_ON_CONTRACT_VIOLATION
49#pragma push_macro("noexcept")
50#define noexcept /* nothing */
51#endif
52
53// turn off some misguided warnings
54#pragma warning(push)
55#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
56#pragma warning(disable : 4512) // warns that assignment op could not be generated
57
58#endif // _MSC_VER <= 1800
59
60#endif // _MSC_VER
61
62#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
63
64#ifdef _MSC_VER
65#pragma push_macro("noexcept")
66#endif
67
68#define noexcept /* nothing */
69
70#endif // GSL_THROW_ON_CONTRACT_VIOLATION
71
72namespace gsl
73{
74
Neil MacIntoshd3929c52016-02-24 16:11:33 -080075// [views.constants], constants
76constexpr const std::ptrdiff_t dynamic_extent = -1;
77
78
79// [span], class template span
80template <class ElementType, std::ptrdiff_t Extent = dynamic_extent>
81class span {
82public:
83 // constants and types
84 using element_type = ElementType;
85 using index_type = std::ptrdiff_t;
86 using pointer = element_type*;
87 using reference = element_type&;
88#if 0 // TODO
89 using iterator = /*implementation-defined */;
90 using const_iterator = /* implementation-defined */;
91 using reverse_iterator = std::reverse_iterator<iterator>;
92 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
93#endif
94 constexpr static const index_type extent = Extent;
95
96 // [span.cons], span constructors, copy, assignment, and destructor
97 constexpr span() noexcept : data_(nullptr), size_(0)
98 { static_assert(extent == dynamic_extent || extent == 0, "Cannot default initialize a fixed-length span."); }
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -080099
100 constexpr span(nullptr_t) noexcept : span()
101 {}
102
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800103 constexpr span(pointer ptr, index_type count) : data_(ptr), size_(count)
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800104 { Expects(((!ptr && count == 0) || (ptr && count >= 0)) && (extent == dynamic_extent || extent == count)); }
105
106 constexpr span(pointer firstElem, pointer lastElem) : data_(firstElem), size_(std::distance(firstElem, lastElem))
107 { Expects(size_ >= 0 && (extent == dynamic_extent || extent == size_)); }
108
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800109 template <size_t N>
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800110 constexpr span(element_type(&arr)[N]) {}
111
112#if 0 // TODO
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800113 template <size_t N>
114 constexpr span(array<remove_const_t<element_type>, N>& arr);
115 template <size_t N>
116 constexpr span(const array<remove_const_t<element_type>, N>& arr);
117 template <class Container>
118 constexpr span(Container& cont);
119 template <class Container>
120 span(const Container&&) = delete;
121 constexpr span(const span& other) noexcept = default;
122 constexpr span(span&& other) noexcept = default;
123 template <class OtherElementType, ptrdiff_t OtherExtent>
124 constexpr span(const span<OtherElementType, OtherExtent>& other);
125 template <class OtherElementType, ptrdiff_t OtherExtent>
126 constexpr span(span<OtherElementType, OtherExtent>&& other);
127 ~span() noexcept = default;
128 constexpr span& operator=(const span& other) noexcept = default;
129 constexpr span& operator=(span&& other) noexcept = default;
130
131 // [span.sub], span subviews
132 template <ptrdiff_t Count>
133 constexpr span<element_type, Count> first() const;
134 template <ptrdiff_t Count>
135 constexpr span<element_type, Count> last() const;
136 template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
137 constexpr span<element_type, Count> subspan() const;
138 constexpr span<element_type, dynamic_extent> first(index_type count) const;
139 constexpr span<element_type, dynamic_extent> last(index_type count) const;
140 constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const;
141#endif
142 // [span.obs], span observers
143 constexpr index_type length() const noexcept { return size(); }
144 constexpr index_type size() const noexcept { return size_; }
145 constexpr index_type length_bytes() const noexcept { return size_bytes(); }
146 constexpr index_type size_bytes() const noexcept { return size() * sizeof(element_type); }
147 constexpr bool empty() const noexcept { return size() == 0; }
148
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800149 // [span.elem], span element access
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800150 constexpr reference operator[](index_type idx) const
151 {
152 Expects(idx >= 0 && idx < size_);
153 return data_[idx];
154 }
155 constexpr reference operator()(index_type idx) const { return this->operator[](idx); }
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800156 constexpr pointer data() const noexcept { return data_; }
157#if 0 // TODO
158 // [span.iter], span iterator support
159 iterator begin() const noexcept;
160 iterator end() const noexcept;
161
162 const_iterator cbegin() const noexcept;
163 const_iterator cend() const noexcept;
164
165 reverse_iterator rbegin() const noexcept;
166 reverse_iterator rend() const noexcept;
167
168 const_reverse_iterator crbegin() const noexcept;
169 const_reverse_iterator crend() const noexcept;
170#endif
171private:
172 pointer data_;
173 index_type size_;
174};
175
176
177#if 0 // TODO
178// [span.comparison], span comparison operators
179template <class ElementType, ptrdiff_t Extent>
180constexpr bool operator==(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
181
182template <class ElementType, ptrdiff_t Extent>
183constexpr bool operator!=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
184
185template <class ElementType, ptrdiff_t Extent>
186constexpr bool operator<(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
187
188template <class ElementType, ptrdiff_t Extent>
189constexpr bool operator<=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
190
191template <class ElementType, ptrdiff_t Extent>
192constexpr bool operator>(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
193
194template <class ElementType, ptrdiff_t Extent>
195constexpr bool operator>=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r) const noexcept;
196#endif
197
198
199#if 0 // TODO
200// [span.objectrep], views of object representation
201template <class ElementType, ptrdiff_t Extent>
202constexpr span<const char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
203
204template <class ElementType, ptrdiff_t Extent>
205constexpr span<char, ((Extent == dynamic_extent) ? dynamic_extent : (sizeof(ElementType) * Extent))> as_writeable_bytes(span<ElementType, Extent>) noexcept;
206#endif
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800207
208} // namespace gsl
209
210#ifdef _MSC_VER
211
212#undef constexpr
213#pragma pop_macro("constexpr")
214
215#if _MSC_VER <= 1800
216#pragma warning(pop)
217
218#ifndef GSL_THROW_ON_CONTRACT_VIOLATION
219#undef noexcept
220#pragma pop_macro("noexcept")
221#endif // GSL_THROW_ON_CONTRACT_VIOLATION
222
223#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
224
225#endif // _MSC_VER <= 1800
226
227#endif // _MSC_VER
228
229#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
230
231#undef noexcept
232
233#ifdef _MSC_VER
234#pragma warning(pop)
235#pragma pop_macro("noexcept")
236#endif
237
238#endif // GSL_THROW_ON_CONTRACT_VIOLATION
239
240#endif // GSL_SPAN_H