blob: 3f54b4825ed2416112d6629fa3a81bb50787c810 [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
Casey Carter4e8f95b2017-02-07 15:59:37 -080022#include <gsl/gsl_assert>
23#include <gsl/gsl_byte>
24#include <gsl/gsl_util>
Tiagoebe7ebf2017-04-20 07:51:37 -070025
Neil MacIntoshcec26a22016-02-24 11:26:28 -080026#include <array>
Neil MacIntoshd3929c52016-02-24 16:11:33 -080027#include <iterator>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -070028#include <limits>
Tiagoebe7ebf2017-04-20 07:51:37 -070029#include <memory>
Neil MacIntoshcec26a22016-02-24 11:26:28 -080030#include <stdexcept>
31#include <type_traits>
32#include <utility>
33
34#ifdef _MSC_VER
Tiagoebe7ebf2017-04-20 07:51:37 -070035#pragma warning(push)
Neil MacIntoshcec26a22016-02-24 11:26:28 -080036
Tiagoebe7ebf2017-04-20 07:51:37 -070037// turn off some warnings that are noisy about our Expects statements
38#pragma warning(disable : 4127) // conditional expression is constant
Neil MacIntoshb2ee4842017-07-13 13:53:56 -070039#pragma warning(disable : 4702) // unreachable code
Neil MacIntosha9f0ce22016-03-31 12:01:07 -070040
Tiagoebe7ebf2017-04-20 07:51:37 -070041// blanket turn off warnings from CppCoreCheck for now
42// so people aren't annoyed by them when running the tool.
43// more targeted suppressions will be added in a future update to the GSL
44#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
Neil MacIntoshcec26a22016-02-24 11:26:28 -080045
Tiagoebe7ebf2017-04-20 07:51:37 -070046#if _MSC_VER < 1910
47#pragma push_macro("constexpr")
48#define constexpr /*constexpr*/
Neil MacIntosha9f0ce22016-03-31 12:01:07 -070049
Tiagoebe7ebf2017-04-20 07:51:37 -070050#endif // _MSC_VER < 1910
51#endif // _MSC_VER
Neil MacIntoshcec26a22016-02-24 11:26:28 -080052
53#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
Tiagoebe7ebf2017-04-20 07:51:37 -070054#define GSL_NOEXCEPT /*noexcept*/
Casey Carter4e8f95b2017-02-07 15:59:37 -080055#else
Tiagoebe7ebf2017-04-20 07:51:37 -070056#define GSL_NOEXCEPT noexcept
Neil MacIntoshcec26a22016-02-24 11:26:28 -080057#endif // GSL_THROW_ON_CONTRACT_VIOLATION
58
59namespace gsl
60{
61
Neil MacIntoshb03b04b2016-07-20 13:17:47 -070062// [views.constants], constants
Neil MacIntoshc94a66f2016-06-12 18:28:19 -070063constexpr const std::ptrdiff_t dynamic_extent = -1;
64
Neil MacIntoshc366f442016-07-26 18:34:27 -070065template <class ElementType, std::ptrdiff_t Extent = dynamic_extent>
66class span;
67
Neil MacIntoshc94a66f2016-06-12 18:28:19 -070068// implementation details
Neil MacIntoshc40094a2016-03-01 12:11:41 -080069namespace details
70{
Neil MacIntoshb03b04b2016-07-20 13:17:47 -070071 template <class T>
72 struct is_span_oracle : std::false_type
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -070073 {
Neil MacIntoshb03b04b2016-07-20 13:17:47 -070074 };
75
76 template <class ElementType, std::ptrdiff_t Extent>
77 struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
78 {
79 };
80
81 template <class T>
Neil MacIntoshc366f442016-07-26 18:34:27 -070082 struct is_span : public is_span_oracle<std::remove_cv_t<T>>
83 {
84 };
85
86 template <class T>
87 struct is_std_array_oracle : std::false_type
88 {
89 };
90
Casey Carter3819df62017-02-13 12:11:45 -080091 template <class ElementType, std::size_t Extent>
Neil MacIntoshc366f442016-07-26 18:34:27 -070092 struct is_std_array_oracle<std::array<ElementType, Extent>> : std::true_type
93 {
94 };
95
96 template <class T>
97 struct is_std_array : public is_std_array_oracle<std::remove_cv_t<T>>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -070098 {
99 };
100
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700101 template <std::ptrdiff_t From, std::ptrdiff_t To>
102 struct is_allowed_extent_conversion
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700103 : public std::integral_constant<bool, From == To || From == gsl::dynamic_extent ||
104 To == gsl::dynamic_extent>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700105 {
106 };
107
108 template <class From, class To>
109 struct is_allowed_element_type_conversion
Neil MacIntosh831be5d2016-09-14 22:01:02 -0700110 : public std::integral_constant<bool, std::is_convertible<From (*)[], To (*)[]>::value>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700111 {
112 };
113
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700114 template <class Span, bool IsConst>
Neil MacIntosh6c7be2c2016-08-01 21:41:20 -0700115 class span_iterator
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700116 {
Eric Niebler9d13cb12016-12-09 20:19:50 -0800117 using element_type_ = typename Span::element_type;
Tiagoebe7ebf2017-04-20 07:51:37 -0700118
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700119 public:
120 using iterator_category = std::random_access_iterator_tag;
Maciej T. Nowakc2f953f2017-04-13 22:55:20 +0200121 using value_type = std::remove_cv_t<element_type_>;
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700122 using difference_type = typename Span::index_type;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700123
Tiagoebe7ebf2017-04-20 07:51:37 -0700124 using reference = std::conditional_t<IsConst, const element_type_, element_type_>&;
Eric Niebler9d13cb12016-12-09 20:19:50 -0800125 using pointer = std::add_pointer_t<reference>;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700126
Casey Carter39902b62017-05-26 15:41:12 -0700127 span_iterator() = default;
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700128
Galik7abfc982017-05-30 16:09:09 +0100129 constexpr span_iterator(const Span* span, typename Span::index_type index) GSL_NOEXCEPT
130 : span_(span), index_(index)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700131 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700132 Expects(span == nullptr || (index_ >= 0 && index <= span_->length()));
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700133 }
134
Casey Carter39902b62017-05-26 15:41:12 -0700135 friend span_iterator<Span, true>;
136 template<bool B, std::enable_if_t<!B && IsConst>* = nullptr>
137 constexpr span_iterator(const span_iterator<Span, B>& other) GSL_NOEXCEPT
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700138 : span_iterator(other.span_, other.index_)
139 {
140 }
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700141
Casey Carter39902b62017-05-26 15:41:12 -0700142 constexpr reference operator*() const GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700143 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700144 Expects(span_);
145 return (*span_)[index_];
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700146 }
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700147
Casey Carter39902b62017-05-26 15:41:12 -0700148 constexpr pointer operator->() const GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700149 {
Casey Carter39902b62017-05-26 15:41:12 -0700150 Expects(span_ && index_ >= 0 && index_ < span_->length());
151 return span_->data() + index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700152 }
153
Casey Carter39902b62017-05-26 15:41:12 -0700154 constexpr span_iterator& operator++() GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700155 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700156 Expects(span_ && index_ >= 0 && index_ < span_->length());
157 ++index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700158 return *this;
159 }
160
Casey Carter4e8f95b2017-02-07 15:59:37 -0800161 constexpr span_iterator operator++(int) GSL_NOEXCEPT
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700162 {
163 auto ret = *this;
164 ++(*this);
165 return ret;
166 }
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700167
Casey Carter39902b62017-05-26 15:41:12 -0700168 constexpr span_iterator& operator--() GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700169 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700170 Expects(span_ && index_ > 0 && index_ <= span_->length());
171 --index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700172 return *this;
173 }
174
Casey Carter4e8f95b2017-02-07 15:59:37 -0800175 constexpr span_iterator operator--(int) GSL_NOEXCEPT
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700176 {
177 auto ret = *this;
178 --(*this);
179 return ret;
180 }
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700181
Casey Carter4e8f95b2017-02-07 15:59:37 -0800182 constexpr span_iterator operator+(difference_type n) const GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700183 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700184 auto ret = *this;
185 return ret += n;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700186 }
187
Casey Carter39902b62017-05-26 15:41:12 -0700188 constexpr span_iterator& operator+=(difference_type n) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700189 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700190 Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length());
191 index_ += n;
192 return *this;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700193 }
194
Casey Carter4e8f95b2017-02-07 15:59:37 -0800195 constexpr span_iterator operator-(difference_type n) const GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700196 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700197 auto ret = *this;
198 return ret -= n;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700199 }
200
Casey Carter4e8f95b2017-02-07 15:59:37 -0800201 constexpr span_iterator& operator-=(difference_type n) GSL_NOEXCEPT { return *this += -n; }
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700202
Casey Carter39902b62017-05-26 15:41:12 -0700203 constexpr difference_type operator-(const span_iterator& rhs) const GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700204 {
Neil MacIntosh94afa1f2016-08-01 18:49:48 -0700205 Expects(span_ == rhs.span_);
206 return index_ - rhs.index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700207 }
208
Tiagoebe7ebf2017-04-20 07:51:37 -0700209 constexpr reference operator[](difference_type n) const GSL_NOEXCEPT
210 {
211 return *(*this + n);
212 }
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700213
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700214 constexpr friend bool operator==(const span_iterator& lhs,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800215 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700216 {
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700217 return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700218 }
219
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700220 constexpr friend bool operator!=(const span_iterator& lhs,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800221 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700222 {
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700223 return !(lhs == rhs);
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700224 }
225
Casey Carter39902b62017-05-26 15:41:12 -0700226 constexpr friend bool operator<(const span_iterator& lhs,
227 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700228 {
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700229 Expects(lhs.span_ == rhs.span_);
230 return lhs.index_ < rhs.index_;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700231 }
232
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700233 constexpr friend bool operator<=(const span_iterator& lhs,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800234 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700235 {
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700236 return !(rhs < lhs);
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700237 }
238
Tiagoebe7ebf2017-04-20 07:51:37 -0700239 constexpr friend bool operator>(const span_iterator& lhs,
240 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700241 {
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700242 return rhs < lhs;
243 }
244
Neil MacIntosh0dd5f562016-08-08 13:33:02 -0700245 constexpr friend bool operator>=(const span_iterator& lhs,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800246 const span_iterator& rhs) GSL_NOEXCEPT
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700247 {
248 return !(rhs > lhs);
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700249 }
250
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700251 protected:
Casey Carter39902b62017-05-26 15:41:12 -0700252 const Span* span_ = nullptr;
253 std::ptrdiff_t index_ = 0;
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700254 };
255
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700256 template <class Span, bool IsConst>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800257 inline constexpr span_iterator<Span, IsConst>
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700258 operator+(typename span_iterator<Span, IsConst>::difference_type n,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800259 const span_iterator<Span, IsConst>& rhs) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700260 {
261 return rhs + n;
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700262 }
263
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700264 template <class Span, bool IsConst>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800265 inline constexpr span_iterator<Span, IsConst>
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700266 operator-(typename span_iterator<Span, IsConst>::difference_type n,
Casey Carter4e8f95b2017-02-07 15:59:37 -0800267 const span_iterator<Span, IsConst>& rhs) GSL_NOEXCEPT
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700268 {
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700269 return rhs - n;
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700270 }
271
Neil MacIntoshc366f442016-07-26 18:34:27 -0700272 template <std::ptrdiff_t Ext>
273 class extent_type
274 {
275 public:
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700276 using index_type = std::ptrdiff_t;
Neil MacIntoshc366f442016-07-26 18:34:27 -0700277
278 static_assert(Ext >= 0, "A fixed-size span must be >= 0 in size.");
279
Casey Carter4e8f95b2017-02-07 15:59:37 -0800280 constexpr extent_type() GSL_NOEXCEPT {}
Neil MacIntoshc366f442016-07-26 18:34:27 -0700281
282 template <index_type Other>
Casey Carter96eaf272017-01-28 00:08:48 -0800283 constexpr extent_type(extent_type<Other> ext)
Neil MacIntoshc366f442016-07-26 18:34:27 -0700284 {
285 static_assert(Other == Ext || Other == dynamic_extent,
286 "Mismatch between fixed-size extent and size of initializing data.");
287 Expects(ext.size() == Ext);
288 }
289
290 constexpr extent_type(index_type size) { Expects(size == Ext); }
291
Casey Carter4e8f95b2017-02-07 15:59:37 -0800292 constexpr index_type size() const GSL_NOEXCEPT { return Ext; }
Neil MacIntoshc366f442016-07-26 18:34:27 -0700293 };
294
295 template <>
296 class extent_type<dynamic_extent>
297 {
298 public:
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700299 using index_type = std::ptrdiff_t;
Neil MacIntoshc366f442016-07-26 18:34:27 -0700300
301 template <index_type Other>
302 explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
303 {
304 }
305
306 explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); }
307
Casey Carter4e8f95b2017-02-07 15:59:37 -0800308 constexpr index_type size() const GSL_NOEXCEPT { return size_; }
Neil MacIntoshc366f442016-07-26 18:34:27 -0700309
310 private:
311 index_type size_;
312 };
Neil MacIntoshc40094a2016-03-01 12:11:41 -0800313} // namespace details
314
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700315// [span], class template span
Neil MacIntoshc40094a2016-03-01 12:11:41 -0800316template <class ElementType, std::ptrdiff_t Extent>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700317class span
318{
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800319public:
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700320 // constants and types
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800321 using element_type = ElementType;
Tiagoebe7ebf2017-04-20 07:51:37 -0700322 using value_type = std::remove_cv_t<ElementType>;
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800323 using index_type = std::ptrdiff_t;
324 using pointer = element_type*;
325 using reference = element_type&;
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700326
Neil MacIntosh82389aa2016-08-08 12:06:47 -0700327 using iterator = details::span_iterator<span<ElementType, Extent>, false>;
328 using const_iterator = details::span_iterator<span<ElementType, Extent>, true>;
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800329 using reverse_iterator = std::reverse_iterator<iterator>;
Neil MacIntosh26747242016-06-26 17:00:56 +0300330 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700331
Maciej T. Nowakc2f953f2017-04-13 22:55:20 +0200332 using size_type = index_type;
333
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800334 constexpr static const index_type extent = Extent;
335
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700336 // [span.cons], span constructors, copy, assignment, and destructor
Casey Carter96eaf272017-01-28 00:08:48 -0800337 template <bool Dependent = false,
Tiagoebe7ebf2017-04-20 07:51:37 -0700338 // "Dependent" is needed to make "std::enable_if_t<Dependent || Extent <= 0>" SFINAE,
339 // since "std::enable_if_t<Extent <= 0>" is ill-formed when Extent is greater than 0.
340 class = std::enable_if_t<(Dependent || Extent <= 0)>>
341 constexpr span() GSL_NOEXCEPT : storage_(nullptr, details::extent_type<0>())
342 {
343 }
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800344
Casey Carter4e8f95b2017-02-07 15:59:37 -0800345 constexpr span(std::nullptr_t) GSL_NOEXCEPT : span() {}
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800346
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700347 constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {}
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800348
Neil MacIntosh502cd662016-02-28 00:50:53 -0800349 constexpr span(pointer firstElem, pointer lastElem)
350 : storage_(firstElem, std::distance(firstElem, lastElem))
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700351 {
352 }
Neil MacIntoshf61a9bb2016-02-29 13:16:48 -0800353
Casey Carter3819df62017-02-13 12:11:45 -0800354 template <std::size_t N>
Tiagoebe7ebf2017-04-20 07:51:37 -0700355 constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT
356 : storage_(&arr[0], details::extent_type<N>())
Neil MacIntoshc366f442016-07-26 18:34:27 -0700357 {
358 }
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700359
Casey Carter3819df62017-02-13 12:11:45 -0800360 template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800361 constexpr span(std::array<ArrayElementType, N>& arr) GSL_NOEXCEPT
Neil MacIntoshc366f442016-07-26 18:34:27 -0700362 : storage_(&arr[0], details::extent_type<N>())
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700363 {
364 }
365
Casey Carter3819df62017-02-13 12:11:45 -0800366 template <std::size_t N>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800367 constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) GSL_NOEXCEPT
Neil MacIntoshc366f442016-07-26 18:34:27 -0700368 : storage_(&arr[0], details::extent_type<N>())
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700369 {
370 }
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800371
Tiagoebe7ebf2017-04-20 07:51:37 -0700372 template <class ArrayElementType = std::add_pointer<element_type>>
373 constexpr span(const std::unique_ptr<ArrayElementType>& ptr, index_type count)
374 : storage_(ptr.get(), count)
375 {
376 }
Rian Quinn2b51b872016-11-03 19:55:41 -0600377
Tiagoebe7ebf2017-04-20 07:51:37 -0700378 constexpr span(const std::unique_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
379 {
380 }
381 constexpr span(const std::shared_ptr<ElementType>& ptr) : storage_(ptr.get(), ptr.get() ? 1 : 0)
382 {
383 }
Rian Quinn2b51b872016-11-03 19:55:41 -0600384
Neil MacIntoshc40094a2016-03-01 12:11:41 -0800385 // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
386 // on Container to be a contiguous sequence container.
387 template <class Container,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700388 class = std::enable_if_t<
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700389 !details::is_span<Container>::value && !details::is_std_array<Container>::value &&
Neil MacIntoshc366f442016-07-26 18:34:27 -0700390 std::is_convertible<typename Container::pointer, pointer>::value &&
391 std::is_convertible<typename Container::pointer,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700392 decltype(std::declval<Container>().data())>::value>>
Gary Furnish612747a2016-10-04 21:13:18 -0600393 constexpr span(Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700394 {
395 }
Neil MacIntoshc40094a2016-03-01 12:11:41 -0800396
Neil MacIntoshc40094a2016-03-01 12:11:41 -0800397 template <class Container,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700398 class = std::enable_if_t<
399 std::is_const<element_type>::value && !details::is_span<Container>::value &&
Neil MacIntoshc366f442016-07-26 18:34:27 -0700400 std::is_convertible<typename Container::pointer, pointer>::value &&
401 std::is_convertible<typename Container::pointer,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700402 decltype(std::declval<Container>().data())>::value>>
Gary Furnish612747a2016-10-04 21:13:18 -0600403 constexpr span(const Container& cont) : span(cont.data(), narrow<index_type>(cont.size()))
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700404 {
405 }
Neil MacIntosh3d4c3492016-03-17 17:20:33 -0700406
Casey Carter4e8f95b2017-02-07 15:59:37 -0800407 constexpr span(const span& other) GSL_NOEXCEPT = default;
Casey Carter4e8f95b2017-02-07 15:59:37 -0800408 constexpr span(span&& other) GSL_NOEXCEPT = default;
Neil MacIntosh717a2e32016-03-16 19:39:55 -0700409
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700410 template <
411 class OtherElementType, std::ptrdiff_t OtherExtent,
Neil MacIntoshc94a66f2016-06-12 18:28:19 -0700412 class = std::enable_if_t<
413 details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700414 details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
415 constexpr span(const span<OtherElementType, OtherExtent>& other)
Neil MacIntosh831be5d2016-09-14 22:01:02 -0700416 : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700417 {
418 }
419
420 template <
421 class OtherElementType, std::ptrdiff_t OtherExtent,
422 class = std::enable_if_t<
423 details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
424 details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
Neil MacIntosh717a2e32016-03-16 19:39:55 -0700425 constexpr span(span<OtherElementType, OtherExtent>&& other)
Neil MacIntosh831be5d2016-09-14 22:01:02 -0700426 : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700427 {
428 }
Neil MacIntosh717a2e32016-03-16 19:39:55 -0700429
Casey Carter4e8f95b2017-02-07 15:59:37 -0800430 ~span() GSL_NOEXCEPT = default;
431 constexpr span& operator=(const span& other) GSL_NOEXCEPT = default;
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800432
Casey Carter4e8f95b2017-02-07 15:59:37 -0800433 constexpr span& operator=(span&& other) GSL_NOEXCEPT = default;
Neil MacIntoshbe43c792017-07-14 04:40:27 -0700434
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700435 // [span.sub], span subviews
Neil MacIntoshc366f442016-07-26 18:34:27 -0700436 template <std::ptrdiff_t Count>
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700437 constexpr span<element_type, Count> first() const
438 {
439 Expects(Count >= 0 && Count <= size());
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700440 return {data(), Count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700441 }
442
Neil MacIntoshc366f442016-07-26 18:34:27 -0700443 template <std::ptrdiff_t Count>
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700444 constexpr span<element_type, Count> last() const
445 {
446 Expects(Count >= 0 && Count <= size());
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700447 return {data() + (size() - Count), Count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700448 }
449
Neil MacIntoshc366f442016-07-26 18:34:27 -0700450 template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700451 constexpr span<element_type, Count> subspan() const
452 {
Neil MacIntoshc366f442016-07-26 18:34:27 -0700453 Expects((Offset == 0 || (Offset > 0 && Offset <= size())) &&
454 (Count == dynamic_extent || (Count >= 0 && Offset + Count <= size())));
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700455 return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700456 }
457
458 constexpr span<element_type, dynamic_extent> first(index_type count) const
459 {
460 Expects(count >= 0 && count <= size());
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700461 return {data(), count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700462 }
463
464 constexpr span<element_type, dynamic_extent> last(index_type count) const
465 {
466 Expects(count >= 0 && count <= size());
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700467 return {data() + (size() - count), count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700468 }
469
470 constexpr span<element_type, dynamic_extent> subspan(index_type offset,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700471 index_type count = dynamic_extent) const
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700472 {
Neil MacIntoshc366f442016-07-26 18:34:27 -0700473 Expects((offset == 0 || (offset > 0 && offset <= size())) &&
474 (count == dynamic_extent || (count >= 0 && offset + count <= size())));
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700475 return {data() + offset, count == dynamic_extent ? size() - offset : count};
Neil MacIntoshc8a412f2016-03-18 16:49:29 -0700476 }
477
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700478 // [span.obs], span observers
Casey Carter4e8f95b2017-02-07 15:59:37 -0800479 constexpr index_type length() const GSL_NOEXCEPT { return size(); }
480 constexpr index_type size() const GSL_NOEXCEPT { return storage_.size(); }
481 constexpr index_type length_bytes() const GSL_NOEXCEPT { return size_bytes(); }
Tiagoebe7ebf2017-04-20 07:51:37 -0700482 constexpr index_type size_bytes() const GSL_NOEXCEPT
483 {
484 return size() * narrow_cast<index_type>(sizeof(element_type));
485 }
Casey Carter4e8f95b2017-02-07 15:59:37 -0800486 constexpr bool empty() const GSL_NOEXCEPT { return size() == 0; }
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800487
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700488 // [span.elem], span element access
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800489 constexpr reference operator[](index_type idx) const
490 {
Neil MacIntosh502cd662016-02-28 00:50:53 -0800491 Expects(idx >= 0 && idx < storage_.size());
Neil MacIntoshf2ab3a52016-07-20 09:24:49 -0700492 return data()[idx];
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800493 }
Rian Quinn6cffe0d2016-10-26 15:11:24 -0600494
495 constexpr reference at(index_type idx) const { return this->operator[](idx); }
Neil MacIntoshcc22f2b2016-02-25 11:42:26 -0800496 constexpr reference operator()(index_type idx) const { return this->operator[](idx); }
Casey Carter4e8f95b2017-02-07 15:59:37 -0800497 constexpr pointer data() const GSL_NOEXCEPT { return storage_.data(); }
Neil MacIntoshd9d6ff02016-05-29 13:52:28 -0700498
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700499 // [span.iter], span iterator support
Casey Carter4e8f95b2017-02-07 15:59:37 -0800500 iterator begin() const GSL_NOEXCEPT { return {this, 0}; }
501 iterator end() const GSL_NOEXCEPT { return {this, length()}; }
Neil MacIntosh30a038c2016-07-18 11:38:01 -0700502
Casey Carter4e8f95b2017-02-07 15:59:37 -0800503 const_iterator cbegin() const GSL_NOEXCEPT { return {this, 0}; }
504 const_iterator cend() const GSL_NOEXCEPT { return {this, length()}; }
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700505
Casey Carter4e8f95b2017-02-07 15:59:37 -0800506 reverse_iterator rbegin() const GSL_NOEXCEPT { return reverse_iterator{end()}; }
507 reverse_iterator rend() const GSL_NOEXCEPT { return reverse_iterator{begin()}; }
Neil MacIntosh30a038c2016-07-18 11:38:01 -0700508
Casey Carter4e8f95b2017-02-07 15:59:37 -0800509 const_reverse_iterator crbegin() const GSL_NOEXCEPT { return const_reverse_iterator{cend()}; }
510 const_reverse_iterator crend() const GSL_NOEXCEPT { return const_reverse_iterator{cbegin()}; }
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800511
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800512private:
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700513 // this implementation detail class lets us take advantage of the
Neil MacIntosh502cd662016-02-28 00:50:53 -0800514 // empty base class optimization to pay for only storage of a single
515 // pointer in the case of fixed-size spans
516 template <class ExtentType>
517 class storage_type : public ExtentType
518 {
519 public:
520 template <class OtherExtentType>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700521 constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
522 {
Neil MacIntosh4de3d4e2016-07-26 18:44:13 -0700523 Expects((!data && ExtentType::size() == 0) || (data && ExtentType::size() >= 0));
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700524 }
Neil MacIntosh502cd662016-02-28 00:50:53 -0800525
Casey Carter4e8f95b2017-02-07 15:59:37 -0800526 constexpr pointer data() const GSL_NOEXCEPT { return data_; }
Neil MacIntosh502cd662016-02-28 00:50:53 -0800527
528 private:
529 pointer data_;
530 };
531
Neil MacIntoshc366f442016-07-26 18:34:27 -0700532 storage_type<details::extent_type<Extent>> storage_;
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800533};
534
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700535// [span.comparison], span comparison operators
Neil MacIntoshc366f442016-07-26 18:34:27 -0700536template <class ElementType, std::ptrdiff_t FirstExtent, std::ptrdiff_t SecondExtent>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800537inline constexpr bool operator==(const span<ElementType, FirstExtent>& l,
Tiagoebe7ebf2017-04-20 07:51:37 -0700538 const span<ElementType, SecondExtent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700539{
540 return std::equal(l.begin(), l.end(), r.begin(), r.end());
541}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800542
Neil MacIntoshc366f442016-07-26 18:34:27 -0700543template <class ElementType, std::ptrdiff_t Extent>
Tiagoebe7ebf2017-04-20 07:51:37 -0700544inline constexpr bool operator!=(const span<ElementType, Extent>& l,
545 const span<ElementType, Extent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700546{
547 return !(l == r);
548}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800549
Neil MacIntoshc366f442016-07-26 18:34:27 -0700550template <class ElementType, std::ptrdiff_t Extent>
Tiagoebe7ebf2017-04-20 07:51:37 -0700551inline constexpr bool operator<(const span<ElementType, Extent>& l,
552 const span<ElementType, Extent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700553{
554 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
555}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800556
Neil MacIntoshc366f442016-07-26 18:34:27 -0700557template <class ElementType, std::ptrdiff_t Extent>
Tiagoebe7ebf2017-04-20 07:51:37 -0700558inline constexpr bool operator<=(const span<ElementType, Extent>& l,
559 const span<ElementType, Extent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700560{
561 return !(l > r);
562}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800563
Neil MacIntoshc366f442016-07-26 18:34:27 -0700564template <class ElementType, std::ptrdiff_t Extent>
Tiagoebe7ebf2017-04-20 07:51:37 -0700565inline constexpr bool operator>(const span<ElementType, Extent>& l,
566 const span<ElementType, Extent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700567{
568 return r < l;
569}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800570
Neil MacIntoshc366f442016-07-26 18:34:27 -0700571template <class ElementType, std::ptrdiff_t Extent>
Tiagoebe7ebf2017-04-20 07:51:37 -0700572inline constexpr bool operator>=(const span<ElementType, Extent>& l,
573 const span<ElementType, Extent>& r)
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700574{
575 return !(l < r);
576}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800577
Neil MacIntoshba8ebef2016-05-29 17:06:29 -0700578namespace details
579{
580 // if we only supported compilers with good constexpr support then
581 // this pair of classes could collapse down to a constexpr function
582
Casey Carter3819df62017-02-13 12:11:45 -0800583 // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700584 // constexpr
Neil MacIntoshba8ebef2016-05-29 17:06:29 -0700585 // and so will fail compilation of the template
Neil MacIntoshc366f442016-07-26 18:34:27 -0700586 template <class ElementType, std::ptrdiff_t Extent>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700587 struct calculate_byte_size
588 : std::integral_constant<std::ptrdiff_t,
Neil MacIntoshc366f442016-07-26 18:34:27 -0700589 static_cast<std::ptrdiff_t>(sizeof(ElementType) *
Neil MacIntosh6fadce92016-07-26 19:19:47 -0700590 static_cast<std::size_t>(Extent))>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700591 {
592 };
Neil MacIntoshba8ebef2016-05-29 17:06:29 -0700593
594 template <class ElementType>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700595 struct calculate_byte_size<ElementType, dynamic_extent>
596 : std::integral_constant<std::ptrdiff_t, dynamic_extent>
597 {
598 };
Neil MacIntoshba8ebef2016-05-29 17:06:29 -0700599}
600
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700601// [span.objectrep], views of object representation
Neil MacIntoshc366f442016-07-26 18:34:27 -0700602template <class ElementType, std::ptrdiff_t Extent>
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700603span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800604as_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700605{
606 return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
607}
Neil MacIntoshd3929c52016-02-24 16:11:33 -0800608
Neil MacIntoshc366f442016-07-26 18:34:27 -0700609template <class ElementType, std::ptrdiff_t Extent,
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700610 class = std::enable_if_t<!std::is_const<ElementType>::value>>
611span<byte, details::calculate_byte_size<ElementType, Extent>::value>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800612as_writeable_bytes(span<ElementType, Extent> s) GSL_NOEXCEPT
Neil MacIntoshb03b04b2016-07-20 13:17:47 -0700613{
614 return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
615}
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800616
Rian Quinn2df9f852016-11-16 11:17:04 -0700617//
618// make_span() - Utility functions for creating spans
619//
620template <class ElementType>
Tiagoebe7ebf2017-04-20 07:51:37 -0700621span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::index_type count)
622{
623 return span<ElementType>(ptr, count);
624}
Rian Quinn2df9f852016-11-16 11:17:04 -0700625
626template <class ElementType>
Tiagoebe7ebf2017-04-20 07:51:37 -0700627span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
628{
629 return span<ElementType>(firstElem, lastElem);
630}
Rian Quinn2df9f852016-11-16 11:17:04 -0700631
Casey Carter3819df62017-02-13 12:11:45 -0800632template <class ElementType, std::size_t N>
ewoudvc64c0ca62017-04-25 21:01:49 +0200633span<ElementType, N> make_span(ElementType (&arr)[N])
Tiagoebe7ebf2017-04-20 07:51:37 -0700634{
ewoudvc64c0ca62017-04-25 21:01:49 +0200635 return span<ElementType, N>(arr);
Tiagoebe7ebf2017-04-20 07:51:37 -0700636}
Rian Quinn2df9f852016-11-16 11:17:04 -0700637
638template <class Container>
Tiagoebe7ebf2017-04-20 07:51:37 -0700639span<typename Container::value_type> make_span(Container& cont)
640{
641 return span<typename Container::value_type>(cont);
642}
Rian Quinn2df9f852016-11-16 11:17:04 -0700643
644template <class Container>
Tiagoebe7ebf2017-04-20 07:51:37 -0700645span<const typename Container::value_type> make_span(const Container& cont)
646{
647 return span<const typename Container::value_type>(cont);
648}
Rian Quinn2df9f852016-11-16 11:17:04 -0700649
650template <class Ptr>
Tiagoebe7ebf2017-04-20 07:51:37 -0700651span<typename Ptr::element_type> make_span(Ptr& cont, std::ptrdiff_t count)
652{
653 return span<typename Ptr::element_type>(cont, count);
654}
Rian Quinn2df9f852016-11-16 11:17:04 -0700655
656template <class Ptr>
Tiagoebe7ebf2017-04-20 07:51:37 -0700657span<typename Ptr::element_type> make_span(Ptr& cont)
658{
659 return span<typename Ptr::element_type>(cont);
660}
Rian Quinn2df9f852016-11-16 11:17:04 -0700661
ericLemanissier134f2db2016-08-23 10:30:06 +0200662// Specialization of gsl::at for span
663template <class ElementType, std::ptrdiff_t Extent>
Casey Carter4e8f95b2017-02-07 15:59:37 -0800664inline constexpr ElementType& at(const span<ElementType, Extent>& s, std::ptrdiff_t index)
ericLemanissier134f2db2016-08-23 10:30:06 +0200665{
666 // No bounds checking here because it is done in span::operator[] called below
667 return s[index];
668}
669
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800670} // namespace gsl
671
Casey Carter4e8f95b2017-02-07 15:59:37 -0800672#undef GSL_NOEXCEPT
673
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800674#ifdef _MSC_VER
Tiagoebe7ebf2017-04-20 07:51:37 -0700675#if _MSC_VER < 1910
676#undef constexpr
677#pragma pop_macro("constexpr")
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800678
Tiagoebe7ebf2017-04-20 07:51:37 -0700679#endif // _MSC_VER < 1910
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800680
Tiagoebe7ebf2017-04-20 07:51:37 -0700681#pragma warning(pop)
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800682#endif // _MSC_VER
683
Neil MacIntoshcec26a22016-02-24 11:26:28 -0800684#endif // GSL_SPAN_H