From cdd9ee5a6ac673fbf632f6b914821bb2cfaf7f05 Mon Sep 17 00:00:00 2001 From: Jeroen Akershoek Date: Tue, 5 Dec 2017 23:42:12 +0200 Subject: [PATCH] Improved conformance of gsl::span for compile-time errors as per 23.7.2.1: - span() and span(nullptr) can only be used if extent is dynamic or 0 - span( element_type(&arr)[N] ) can only be used if extent is dynamic or N - std::array can be used for initialization if extent is dynamic or size of the array - Containers can be used for initialization if pointer type is convertible as per 23.7.2.2 - first and last may no longer exceed the span extents --- include/gsl/span | 35 +++++++++++++++++++++++------------ tests/span_tests.cpp | 1 + 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index bd9a21d..7cfdadd 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -342,6 +342,7 @@ public: { } + template > constexpr span(std::nullptr_t) GSL_NOEXCEPT : span() {} constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {} @@ -351,19 +352,28 @@ public: { } - template + template > constexpr span(element_type (&arr)[N]) GSL_NOEXCEPT : storage_(&arr[0], details::extent_type()) { } - template > - constexpr span(std::array& arr) GSL_NOEXCEPT + template , + class = std::enable_if_t< + ( extent == dynamic_extent || N == extent ) && + std::is_convertible_v, pointer> + >> + constexpr span( std::array& arr ) : storage_(&arr[0], details::extent_type()) { } - template + template && + std::is_convertible_v, pointer> + >> constexpr span(const std::array, N>& arr) GSL_NOEXCEPT : storage_(&arr[0], details::extent_type()) { @@ -387,9 +397,7 @@ public: template ::value && !details::is_std_array::value && - std::is_convertible::value && - std::is_convertible().data())>::value>> + std::is_convertible().data()), pointer>::value>> constexpr span(Container& cont) : span(cont.data(), narrow(cont.size())) { } @@ -397,9 +405,8 @@ public: template ::value && !details::is_span::value && - std::is_convertible::value && - std::is_convertible().data())>::value>> + !details::is_std_array::value && + std::is_convertible().data()), pointer>::value>> constexpr span(const Container& cont) : span(cont.data(), narrow(cont.size())) { } @@ -433,14 +440,18 @@ public: constexpr span& operator=(span&& other) GSL_NOEXCEPT = default; // [span.sub], span subviews - template + template = 0 && ( extent == dynamic_extent || Count <= extent )>> constexpr span first() const { Expects(Count >= 0 && Count <= size()); return {data(), Count}; } - template + template = 0 && ( extent == dynamic_extent || Count <= extent )>> constexpr span last() const { Expects(Count >= 0 && size() - Count >= 0); diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index b14ddf0..e0d16c9 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -23,6 +23,7 @@ #include // for array #include // for ptrdiff_t #include // for reverse_iterator, operator-, operator== +#include // for std::map #include // for unique_ptr, shared_ptr, make_unique, allo... #include // for match_results, sub_match, match_results<>... #include // for ptrdiff_t