diff --git a/.clang-format b/.clang-format index b80d2c6..78696f5 100644 --- a/.clang-format +++ b/.clang-format @@ -16,6 +16,6 @@ AllowShortLoopsOnASingleLine: true PointerAlignment: Left AlignConsecutiveAssignments: false -AlignTrailingComments: false +AlignTrailingComments: true SpaceAfterCStyleCast: true diff --git a/include/gsl.h b/include/gsl.h index f4c9178..8e00a44 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -1,17 +1,17 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// /////////////////////////////////////////////////////////////////////////////// #pragma once @@ -19,39 +19,38 @@ #ifndef GSL_GSL_H #define GSL_GSL_H -#include "gsl_assert.h" // Ensures/Expects -#include "gsl_util.h" // finally()/narrow()/narrow_cast()... -#include "span.h" // span -#include "multi_span.h" // multi_span, strided_span... -#include "string_span.h" // zstring, string_span, zstring_builder... +#include "gsl_assert.h" // Ensures/Expects +#include "gsl_util.h" // finally()/narrow()/narrow_cast()... +#include "multi_span.h" // multi_span, strided_span... +#include "span.h" // span +#include "string_span.h" // zstring, string_span, zstring_builder... #include #ifdef _MSC_VER // No MSVC does constexpr fully yet #pragma push_macro("constexpr") -#define constexpr +#define constexpr // MSVC 2013 workarounds #if _MSC_VER <= 1800 -// noexcept is not understood +// noexcept is not understood #pragma push_macro("noexcept") -#define noexcept +#define noexcept // turn off some misguided warnings #pragma warning(push) -#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior +#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #endif // _MSC_VER <= 1800 #endif // _MSC_VER - namespace gsl { // -// GSL.owner: ownership pointers +// GSL.owner: ownership pointers // using std::unique_ptr; using std::shared_ptr; @@ -59,67 +58,74 @@ using std::shared_ptr; template using owner = T; - // // not_null // // Restricts a pointer or smart pointer to only hold non-null values. -// +// // Has zero size overhead over T. // -// If T is a pointer (i.e. T == U*) then -// - allow construction from U* or U& +// If T is a pointer (i.e. T == U*) then +// - allow construction from U* or U& // - disallow construction from nullptr_t // - disallow default construction // - ensure construction from U* fails with nullptr // - allow implicit conversion to U* // -template +template class not_null { static_assert(std::is_assignable::value, "T cannot be assigned nullptr."); + public: not_null(T t) : ptr_(t) { ensure_invariant(); } - not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; } + not_null& operator=(const T& t) + { + ptr_ = t; + ensure_invariant(); + return *this; + } - not_null(const not_null &other) = default; - not_null& operator=(const not_null &other) = default; + not_null(const not_null& other) = default; + not_null& operator=(const not_null& other) = default; template ::value>> - not_null(const not_null &other) + not_null(const not_null& other) { *this = other; } template ::value>> - not_null& operator=(const not_null &other) + not_null& operator=(const not_null& other) { ptr_ = other.get(); return *this; } - // prevents compilation when someone attempts to assign a nullptr + // prevents compilation when someone attempts to assign a nullptr not_null(std::nullptr_t) = delete; not_null(int) = delete; not_null& operator=(std::nullptr_t) = delete; - not_null& operator=(int) = delete; - - T get() const { + not_null& operator=(int) = delete; + + T get() const + { #ifdef _MSC_VER __assume(ptr_ != nullptr); #endif return ptr_; } // the assume() should help the optimizer - operator T() const { return get(); } + operator T() const { return get(); } T operator->() const { return get(); } - bool operator==(const T& rhs) const { return ptr_ == rhs; } - bool operator!=(const T& rhs) const { return !(*this == rhs); } + bool operator==(const T& rhs) const { return ptr_ == rhs; } + bool operator!=(const T& rhs) const { return !(*this == rhs); } private: T ptr_; - // we assume that the compiler can hoist/prove away most of the checks inlined from this function + // we assume that the compiler can hoist/prove away most of the checks inlined from this + // function // if not, we could make them optional via conditional compilation void ensure_invariant() const { Expects(ptr_ != nullptr); } @@ -139,14 +145,11 @@ private: namespace std { - template - struct hash> - { - size_t operator()(const gsl::not_null & value) const - { - return hash{}(value); - } - }; +template +struct hash> +{ + size_t operator()(const gsl::not_null& value) const { return hash{}(value); } +}; } // namespace std @@ -159,7 +162,7 @@ namespace std #undef noexcept #pragma pop_macro("noexcept") - + #pragma warning(pop) #endif // _MSC_VER <= 1800 diff --git a/include/gsl_assert.h b/include/gsl_assert.h index 51e8ab6..10de31a 100644 --- a/include/gsl_assert.h +++ b/include/gsl_assert.h @@ -1,17 +1,17 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// /////////////////////////////////////////////////////////////////////////////// #pragma once @@ -28,50 +28,50 @@ // // 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default) // 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown -// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens +// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens // -#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)) -#define GSL_TERMINATE_ON_CONTRACT_VIOLATION +#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ \ + defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)) +#define GSL_TERMINATE_ON_CONTRACT_VIOLATION #endif - #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) - // // GSL.assert: assertions // namespace gsl { -struct fail_fast : public std::runtime_error +struct fail_fast : public std::runtime_error { - explicit fail_fast(char const* const message) : std::runtime_error(message) {} + explicit fail_fast(char const* const message) : std::runtime_error(message) {} }; } #if defined(GSL_THROW_ON_CONTRACT_VIOLATION) -#define Expects(cond) if (!(cond)) \ - throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)); -#define Ensures(cond) if (!(cond)) \ - throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)); - +#define Expects(cond) \ + if (!(cond)) \ + throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)); +#define Ensures(cond) \ + if (!(cond)) \ + throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ \ + ": " GSL_STRINGIFY(__LINE__)); #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) - -#define Expects(cond) if (!(cond)) std::terminate(); -#define Ensures(cond) if (!(cond)) std::terminate(); - +#define Expects(cond) \ + if (!(cond)) std::terminate(); +#define Ensures(cond) \ + if (!(cond)) std::terminate(); #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) -#define Expects(cond) -#define Ensures(cond) - -#endif +#define Expects(cond) +#define Ensures(cond) +#endif #endif // GSL_CONTRACTS_H diff --git a/include/gsl_byte.h b/include/gsl_byte.h index e2c79c9..5a9c327 100644 --- a/include/gsl_byte.h +++ b/include/gsl_byte.h @@ -1,17 +1,17 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015 Microsoft Corporation. All rights reserved. -// -// This code is licensed under the MIT License (MIT). -// -// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// /////////////////////////////////////////////////////////////////////////////// #pragma once @@ -26,11 +26,11 @@ // constexpr is not understood #pragma push_macro("constexpr") -#define constexpr +#define constexpr -// noexcept is not understood +// noexcept is not understood #pragma push_macro("noexcept") -#define noexcept +#define noexcept #endif // _MSC_VER <= 1800 @@ -38,54 +38,76 @@ namespace gsl { - // This is a simple definition for now that allows - // use of byte within span<> to be standards-compliant - enum class byte : unsigned char {}; +// This is a simple definition for now that allows +// use of byte within span<> to be standards-compliant +enum class byte : unsigned char +{ +}; - template ::value>> - constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept - { return b = byte(static_cast(b) << shift); } +template ::value>> +constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) << shift); +} - template ::value>> - constexpr byte operator<<(byte b, IntegerType shift) noexcept - { return byte(static_cast(b) << shift); } +template ::value>> +constexpr byte operator<<(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) << shift); +} - template ::value>> - constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept - { return b = byte(static_cast(b) >> shift); } +template ::value>> +constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) >> shift); +} - template ::value>> - constexpr byte operator>> (byte b, IntegerType shift) noexcept - { return byte(static_cast(b) >> shift); } +template ::value>> +constexpr byte operator>>(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) >> shift); +} - constexpr byte& operator|=(byte& l, byte r) noexcept - { return l = byte(static_cast(l) | static_cast(r)); } +constexpr byte& operator|=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) | static_cast(r)); +} - constexpr byte operator|(byte l, byte r) noexcept - { return byte(static_cast(l) + static_cast(r)); } +constexpr byte operator|(byte l, byte r) noexcept +{ + return byte(static_cast(l) + static_cast(r)); +} - constexpr byte& operator&=(byte& l, byte r) noexcept - { return l = byte(static_cast(l) & static_cast(r)); } +constexpr byte& operator&=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) & static_cast(r)); +} - constexpr byte operator&(byte l, byte r) noexcept - { return byte(static_cast(l) & static_cast(r)); } +constexpr byte operator&(byte l, byte r) noexcept +{ + return byte(static_cast(l) & static_cast(r)); +} - constexpr byte& operator^=(byte& l, byte r) noexcept - { return l = byte(static_cast(l) ^ static_cast(r)); } - - constexpr byte operator^(byte l, byte r) noexcept - { return byte(static_cast(l) ^ static_cast(r)); } - - constexpr byte operator~(byte b) noexcept - { return byte(~static_cast(b)); } +constexpr byte& operator^=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) ^ static_cast(r)); +} - template ::value>> - constexpr IntegerType to_integer(byte b) noexcept { return {b}; } +constexpr byte operator^(byte l, byte r) noexcept +{ + return byte(static_cast(l) ^ static_cast(r)); +} + +constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); } + +template ::value>> +constexpr IntegerType to_integer(byte b) noexcept +{ + return {b}; +} - } // namespace gsl - #ifdef _MSC_VER #if _MSC_VER <= 1800 diff --git a/include/gsl_util.h b/include/gsl_util.h index d82937f..a3d5fbe 100644 --- a/include/gsl_util.h +++ b/include/gsl_util.h @@ -19,11 +19,11 @@ #ifndef GSL_UTIL_H #define GSL_UTIL_H -#include "gsl_assert.h" // Ensures/Expects +#include "gsl_assert.h" // Ensures/Expects #include -#include -#include #include +#include +#include #ifdef _MSC_VER @@ -32,7 +32,7 @@ #define constexpr #pragma warning(push) -#pragma warning(disable: 4127) // conditional expression is constant +#pragma warning(disable : 4127) // conditional expression is constant // MSVC 2013 workarounds #if _MSC_VER <= 1800 @@ -42,13 +42,12 @@ // turn off some misguided warnings #pragma warning(push) -#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior +#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior #endif // _MSC_VER <= 1800 #endif // _MSC_VER - namespace gsl { // @@ -60,18 +59,20 @@ template class final_act { public: - explicit final_act(F f) noexcept - : f_(std::move(f)), invoke_(true) - {} + explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {} - final_act(final_act&& other) noexcept - : f_(std::move(other.f_)), invoke_(other.invoke_) - { other.invoke_ = false; } + final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_) + { + other.invoke_ = false; + } final_act(const final_act&) = delete; final_act& operator=(const final_act&) = delete; - ~final_act() noexcept { if (invoke_) f_(); } + ~final_act() noexcept + { + if (invoke_) f_(); + } private: F f_; @@ -80,35 +81,44 @@ private: // finally() - convenience function to generate a final_act template -inline final_act finally(const F &f) -noexcept { return final_act(f); } +inline final_act finally(const F& f) noexcept +{ + return final_act(f); +} template -inline final_act finally(F &&f) noexcept -{ return final_act(std::forward(f)); } +inline final_act finally(F&& f) noexcept +{ + return final_act(std::forward(f)); +} // narrow_cast(): a searchable way to do narrowing casts of values -template +template inline constexpr T narrow_cast(U u) noexcept -{ return static_cast(u); } +{ + return static_cast(u); +} -struct narrowing_error : public std::exception {}; +struct narrowing_error : public std::exception +{ +}; namespace details { - template - struct is_same_signedness : public std::integral_constant::value == std::is_signed::value> - {}; + template + struct is_same_signedness + : public std::integral_constant::value == std::is_signed::value> + { + }; } // narrow() : a checked version of narrow_cast() that throws if the cast changed the value -template +template inline T narrow(U u) { T t = narrow_cast(u); - if (static_cast(t) != u) - throw narrowing_error(); -#pragma warning(suppress:4127) // suppress warning from MSVC compiler about constant in if-test + if (static_cast(t) != u) throw narrowing_error(); +#pragma warning(suppress : 4127) // suppress warning from MSVC compiler about constant in if-test if (!details::is_same_signedness::value && ((t < T{}) != (u < U{}))) throw narrowing_error(); return t; @@ -118,24 +128,35 @@ inline T narrow(U u) // at() - Bounds-checked way of accessing static arrays, std::array, std::vector // template -constexpr T& at(T(&arr)[N], size_t index) -{ Expects(index < N); return arr[index]; } +constexpr T& at(T (&arr)[N], size_t index) +{ + Expects(index < N); + return arr[index]; +} template constexpr T& at(std::array& arr, size_t index) -{ Expects(index < N); return arr[index]; } +{ + Expects(index < N); + return arr[index]; +} template constexpr typename Cont::value_type& at(Cont& cont, size_t index) -{ Expects(index < cont.size()); return cont[index]; } +{ + Expects(index < cont.size()); + return cont[index]; +} template constexpr const T& at(std::initializer_list cont, size_t index) -{ Expects(index < cont.size()); return *(cont.begin() + index); } +{ + Expects(index < cont.size()); + return *(cont.begin() + index); +} } // namespace gsl - #ifdef _MSC_VER #pragma warning(pop) diff --git a/include/multi_span.h b/include/multi_span.h index c4a0eac..a63f8ce 100644 --- a/include/multi_span.h +++ b/include/multi_span.h @@ -20,8 +20,8 @@ #define GSL_MULTI_SPAN_H #include "gsl_assert.h" -#include "gsl_util.h" #include "gsl_byte.h" +#include "gsl_util.h" #include #include #include @@ -52,7 +52,7 @@ #define GSL_MSVC_HAS_VARIADIC_CTOR_BUG #define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT -// noexcept is not understood +// noexcept is not understood #ifndef GSL_THROW_ON_CONTRACT_VIOLATION #pragma push_macro("noexcept") #define noexcept /* nothing */ @@ -217,10 +217,7 @@ public: return ret; } - friend constexpr index operator*(value_type v, const index& rhs) noexcept - { - return rhs * v; - } + friend constexpr index operator*(value_type v, const index& rhs) noexcept { return rhs * v; } constexpr index& operator*=(value_type v) noexcept { @@ -743,8 +740,7 @@ public: } constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept - : m_extents(extents), - m_strides(strides) + : m_extents(extents), m_strides(strides) { } @@ -841,8 +837,7 @@ public: using index_size_type = typename IndexType::value_type; template explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept - : boundary_(bnd.index_bounds()), - curr_(std::move(curr)) + : boundary_(bnd.index_bounds()), curr_(std::move(curr)) { static_assert(is_bounds::value, "Bounds type must be provided"); } @@ -930,7 +925,7 @@ public: return ret -= n; } - constexpr bounds_iterator& operator-=(difference_type n) noexcept { return * this += -n; } + constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; } constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept { @@ -1137,7 +1132,7 @@ namespace details template std::enable_if_t< !std::is_same>::value && !std::is_same::value, T> - static_as_span_helper(Arg, Args... args) + static_as_span_helper(Arg, Args... args) { return static_as_span_helper(args...); } @@ -1159,7 +1154,8 @@ namespace details }; template - struct is_multi_span_oracle> : std::true_type + struct is_multi_span_oracle> + : std::true_type { }; @@ -1249,11 +1245,13 @@ public: constexpr multi_span(value_type&&) = delete; // construct from pointer + length - constexpr multi_span(pointer ptr, size_type size) noexcept : multi_span(ptr, bounds_type{size}) {} + constexpr multi_span(pointer ptr, size_type size) noexcept : multi_span(ptr, bounds_type{size}) + { + } // construct from pointer + length - multidimensional - constexpr multi_span(pointer data, bounds_type bounds) noexcept : data_(data), - bounds_(std::move(bounds)) + constexpr multi_span(pointer data, bounds_type bounds) noexcept + : data_(data), bounds_(std::move(bounds)) { Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0); } @@ -1263,7 +1261,8 @@ public: typename = std::enable_if_t::value && details::LessThan::value>> constexpr multi_span(pointer begin, Ptr end) - : multi_span(begin, details::newBoundsHelper(static_cast(end) - begin)) + : multi_span(begin, + details::newBoundsHelper(static_cast(end) - begin)) { Expects(begin != nullptr && end != nullptr && begin <= static_cast(end)); } @@ -1273,9 +1272,8 @@ public: constexpr multi_span(T (&arr)[N]) : multi_span(reinterpret_cast(arr), bounds_type{typename Helper::bounds_type{}}) { - static_assert( - std::is_convertible::value, - "Cannot convert from source type to target multi_span type."); + static_assert(std::is_convertible::value, + "Cannot convert from source type to target multi_span type."); static_assert(std::is_convertible::value, "Cannot construct a multi_span from an array with fewer elements."); } @@ -1286,17 +1284,17 @@ public: constexpr multi_span(T* const& data, size_type size) : multi_span(reinterpret_cast(data), typename Helper::bounds_type{size}) { - static_assert( - std::is_convertible::value, - "Cannot convert from source type to target multi_span type."); + static_assert(std::is_convertible::value, + "Cannot convert from source type to target multi_span type."); } // construct from std::array template - constexpr multi_span(std::array& arr) : multi_span(arr.data(), bounds_type{static_bounds{}}) + constexpr multi_span(std::array& arr) + : multi_span(arr.data(), bounds_type{static_bounds{}}) { static_assert( - std::is_convertible(*) []>::value, + std::is_convertible(*)[]>::value, "Cannot convert from source type to target multi_span type."); static_assert(std::is_convertible, bounds_type>::value, "You cannot construct a multi_span from a std::array of smaller size."); @@ -1307,7 +1305,7 @@ public: constexpr multi_span(const std::array, N>& arr) : multi_span(arr.data(), static_bounds()) { - static_assert(std::is_convertible>::value, + static_assert(std::is_convertible>::value, "Cannot convert from source type to target multi_span type."); static_assert(std::is_convertible, bounds_type>::value, "You cannot construct a multi_span from a std::array of smaller size."); @@ -1329,7 +1327,7 @@ public: DataType>::value>> constexpr multi_span(Cont& cont) : multi_span(static_cast(cont.data()), - details::newBoundsHelper(narrow_cast(cont.size()))) + details::newBoundsHelper(narrow_cast(cont.size()))) { } @@ -1348,8 +1346,8 @@ public: typename OtherBounds = static_bounds, typename = std::enable_if_t::value && std::is_convertible::value>> - constexpr multi_span(multi_span other) noexcept : data_(other.data_), - bounds_(other.bounds_) + constexpr multi_span(multi_span other) noexcept + : data_(other.data_), bounds_(other.bounds_) { } @@ -1424,7 +1422,8 @@ public: // subspan() - create a subview of count elements starting at offset // supplying dynamic_range for count will consume all available elements from offset constexpr multi_span subspan(size_type offset, - size_type count = dynamic_range) const noexcept + size_type count = dynamic_range) const + noexcept { Expects((offset >= 0 && offset <= this->size()) && (count == dynamic_range || (count <= this->size() - offset))); @@ -1535,7 +1534,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator==(const multi_span& other) const noexcept + constexpr bool operator==(const multi_span& other) const + noexcept { return bounds_.size() == other.bounds_.size() && (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); @@ -1544,7 +1544,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator!=(const multi_span& other) const noexcept + constexpr bool operator!=(const multi_span& other) const + noexcept { return !(*this == other); } @@ -1552,7 +1553,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator<(const multi_span& other) const noexcept + constexpr bool operator<(const multi_span& other) const + noexcept { return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); } @@ -1560,7 +1562,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator<=(const multi_span& other) const noexcept + constexpr bool operator<=(const multi_span& other) const + noexcept { return !(other < *this); } @@ -1568,7 +1571,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator>(const multi_span& other) const noexcept + constexpr bool operator>(const multi_span& other) const + noexcept { return (other < *this); } @@ -1576,7 +1580,8 @@ public: template , std::remove_cv_t>::value>> - constexpr bool operator>=(const multi_span& other) const noexcept + constexpr bool operator>=(const multi_span& other) const + noexcept { return !(*this < other); } @@ -1590,8 +1595,8 @@ public: // DimCount and Enabled here are workarounds for a bug in MSVC 2015 template 0), typename = std::enable_if_t> -constexpr multi_span as_span(SpanType s, - Dimensions2... dims) +constexpr multi_span +as_span(SpanType s, Dimensions2... dims) { static_assert(details::is_multi_span::value, "Variadic as_span() is for reshaping existing spans."); @@ -1628,13 +1633,13 @@ multi_span as_writeable_bytes(multi_span s) noexcept // on all implementations. It should be considered an experimental extension // to the standard GSL interface. template -constexpr auto as_span(multi_span s) noexcept - -> multi_span( - multi_span::bounds_type::static_size != dynamic_range - ? (static_cast( - multi_span::bounds_type::static_size) / - sizeof(U)) - : dynamic_range)> +constexpr auto as_span(multi_span s) noexcept -> multi_span< + const U, static_cast( + multi_span::bounds_type::static_size != dynamic_range + ? (static_cast( + multi_span::bounds_type::static_size) / + sizeof(U)) + : dynamic_range)> { using ConstByteSpan = multi_span; static_assert( @@ -1653,12 +1658,13 @@ constexpr auto as_span(multi_span s) noexcept // on all implementations. It should be considered an experimental extension // to the standard GSL interface. template -constexpr auto as_span(multi_span s) noexcept -> multi_span< - U, narrow_cast( - multi_span::bounds_type::static_size != dynamic_range - ? static_cast(multi_span::bounds_type::static_size) / - sizeof(U) - : dynamic_range)> +constexpr auto as_span(multi_span s) noexcept + -> multi_span( + multi_span::bounds_type::static_size != dynamic_range + ? static_cast( + multi_span::bounds_type::static_size) / + sizeof(U) + : dynamic_range)> { using ByteSpan = multi_span; static_assert( @@ -1816,9 +1822,9 @@ public: auto d = narrow_cast(sizeof(OtherValueType) / sizeof(value_type)); size_type size = this->bounds().total_size() / d; - return {const_cast(reinterpret_cast(this->data())), size, - bounds_type{resize_extent(this->bounds().index_bounds(), d), - resize_stride(this->bounds().strides(), d)}}; + return {const_cast(reinterpret_cast(this->data())), + size, bounds_type{resize_extent(this->bounds().index_bounds(), d), + resize_stride(this->bounds().strides(), d)}}; } constexpr strided_span section(index_type origin, index_type extents) const @@ -2049,7 +2055,7 @@ public: contiguous_span_iterator ret{*this}; return ret -= n; } - contiguous_span_iterator& operator-=(difference_type n) noexcept { return * this += -n; } + contiguous_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; } difference_type operator-(const contiguous_span_iterator& rhs) const noexcept { Expects(m_validator == rhs.m_validator); @@ -2148,16 +2154,13 @@ public: general_span_iterator ret{*this}; return ret -= n; } - general_span_iterator& operator-=(difference_type n) noexcept { return * this += -n; } + general_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; } difference_type operator-(const general_span_iterator& rhs) const noexcept { Expects(m_container == rhs.m_container); return m_itr - rhs.m_itr; } - value_type operator[](difference_type n) const noexcept - { - return (*m_container)[m_itr[n]]; - } + value_type operator[](difference_type n) const noexcept { return (*m_container)[m_itr[n]]; } bool operator==(const general_span_iterator& rhs) const noexcept { diff --git a/include/span.h b/include/span.h index 0bffb4b..f40a7ab 100644 --- a/include/span.h +++ b/include/span.h @@ -20,11 +20,11 @@ #define GSL_SPAN_H #include "gsl_assert.h" -#include "gsl_util.h" #include "gsl_byte.h" +#include "gsl_util.h" #include -#include #include +#include #include #include #include @@ -39,7 +39,7 @@ // blanket turn off warnings from CppCoreCheck for now // so people aren't annoyed by them when running the tool. // more targeted suppressions will be added in a future update to the GSL -#pragma warning(disable: 26481 26482 26483 26485 26490 26491 26492 26493 26495) +#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) // No MSVC does constexpr fully yet #pragma push_macro("constexpr") @@ -51,7 +51,7 @@ #define GSL_MSVC_HAS_VARIADIC_CTOR_BUG #define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT -// noexcept is not understood +// noexcept is not understood #ifndef GSL_THROW_ON_CONTRACT_VIOLATION #pragma push_macro("noexcept") #define noexcept /* nothing */ @@ -82,290 +82,340 @@ namespace gsl template class span; - -// [views.constants], constants +// [views.constants], constants constexpr const std::ptrdiff_t dynamic_extent = -1; - // implementation details namespace details { -template -struct is_span_oracle : std::false_type -{ -}; - -template -struct is_span_oracle> : std::true_type -{ -}; - -template -struct is_span : is_span_oracle> -{ -}; - -template -struct is_allowed_pointer_conversion - : std::bool_constant< - std::is_pointer::value && - std::is_pointer::value && - std::is_convertible::value - > -{ -}; - -template -struct is_allowed_integral_conversion - : std::bool_constant< - std::is_integral::value && - std::is_integral::value && - sizeof(From) == sizeof(To) && - alignof(From) == alignof(To) && - std::is_convertible::value - > -{ -}; - -template -struct is_allowed_extent_conversion - : std::bool_constant< - From == To || - From == gsl::dynamic_extent || - To == gsl::dynamic_extent - > -{ -}; - -template -struct is_allowed_element_type_conversion - : std::bool_constant< - std::is_same>::value || - is_allowed_pointer_conversion::value || - is_allowed_integral_conversion::value - > -{ -}; - -template -struct is_allowed_element_type_conversion - : std::bool_constant::value> -{ -}; - -template -struct is_allowed_element_type_conversion - : std::true_type -{ -}; - -template -class const_span_iterator -{ -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = typename Span::element_type; - using difference_type = std::ptrdiff_t; - - using const_pointer = std::add_const_t; - using pointer = const_pointer; - - using const_reference = std::add_const_t; - using reference = const_reference; - - constexpr const_span_iterator() : const_span_iterator(nullptr, 0) {} - constexpr const_span_iterator(const Span* span, typename Span::index_type index) : span_(span), index_(index) + template + struct is_span_oracle : std::false_type { - Expects(span == nullptr || (index_ >= 0 && index <= span_->length())); + }; + + template + struct is_span_oracle> : std::true_type + { + }; + + template + struct is_span : is_span_oracle> + { + }; + + template + struct is_allowed_pointer_conversion + : std::bool_constant::value && std::is_pointer::value && + std::is_convertible::value> + { + }; + + template + struct is_allowed_integral_conversion + : std::bool_constant::value && std::is_integral::value && + sizeof(From) == sizeof(To) && alignof(From) == alignof(To) && + std::is_convertible::value> + { + }; + + template + struct is_allowed_extent_conversion + : std::bool_constant + { + }; + + template + struct is_allowed_element_type_conversion + : std::bool_constant>::value || + is_allowed_pointer_conversion::value || + is_allowed_integral_conversion::value> + { + }; + + template + struct is_allowed_element_type_conversion + : std::bool_constant::value> + { + }; + + template + struct is_allowed_element_type_conversion : std::true_type + { + }; + + template + class const_span_iterator + { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = typename Span::element_type; + using difference_type = std::ptrdiff_t; + + using const_pointer = std::add_const_t; + using pointer = const_pointer; + + using const_reference = std::add_const_t; + using reference = const_reference; + + constexpr const_span_iterator() : const_span_iterator(nullptr, 0) {} + constexpr const_span_iterator(const Span* span, typename Span::index_type index) + : span_(span), index_(index) + { + Expects(span == nullptr || (index_ >= 0 && index <= span_->length())); + } + + constexpr reference operator*() const + { + Expects(span_); + return (*span_)[index_]; + } + constexpr pointer operator->() const + { + Expects(span_); + return &((*span_)[index_]); + } + + constexpr const_span_iterator& operator++() noexcept + { + Expects(span_ && index_ >= 0 && index_ < span_->length()); + ++index_; + return *this; + } + + constexpr const_span_iterator operator++(int) noexcept + { + auto ret = *this; + ++(*this); + return ret; + } + + constexpr const_span_iterator& operator--() noexcept + { + Expects(span_ && index_ > 0 && index_ <= span_->length()); + --index_; + return *this; + } + + constexpr const_span_iterator operator--(int) noexcept + { + auto ret = *this; + --(*this); + return ret; + } + + constexpr const_span_iterator operator+(difference_type n) const noexcept + { + auto ret{*this}; + return ret += n; + } + + constexpr const_span_iterator& operator+=(difference_type n) noexcept + { + Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length()); + index_ += n; + return *this; + } + + constexpr const_span_iterator operator-(difference_type n) const noexcept + { + auto ret{*this}; + return ret -= n; + } + + constexpr const_span_iterator& operator-=(difference_type n) noexcept + { + return *this += -n; + } + + constexpr difference_type operator-(const const_span_iterator& rhs) const noexcept + { + Expects(span_ == rhs.span_); + return index_ - rhs.index_; + } + + constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } + + constexpr bool operator==(const const_span_iterator& rhs) const noexcept + { + return span_ == rhs.span_ && index_ == rhs.index_; + } + + constexpr bool operator!=(const const_span_iterator& rhs) const noexcept + { + return !(*this == rhs); + } + + constexpr bool operator<(const const_span_iterator& rhs) const noexcept + { + Expects(span_ == rhs.span_); + return index_ < rhs.index_; + } + + constexpr bool operator<=(const const_span_iterator& rhs) const noexcept + { + return !(rhs < *this); + } + + constexpr bool operator>(const const_span_iterator& rhs) const noexcept + { + return rhs < *this; + } + + constexpr bool operator>=(const const_span_iterator& rhs) const noexcept + { + return !(rhs > *this); + } + + void swap(const_span_iterator& rhs) noexcept + { + std::swap(index_, rhs.index_); + std::swap(m_span, rhs.m_span); + } + + private: + const Span* span_; + ptrdiff_t index_; + }; + + template + class span_iterator : public const_span_iterator + { + using base_type = const_span_iterator; + + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = typename Span::element_type; + using difference_type = std::ptrdiff_t; + + using pointer = value_type*; + using reference = value_type&; + + constexpr span_iterator() : base_type() {} + constexpr span_iterator(const Span* span, typename Span::index_type index) + : base_type(span, index) + { + } + + constexpr reference operator*() const + { + return const_cast(base_type::operator*()); + } + constexpr pointer operator->() const + { + return const_cast(base_type::operator->()); + } + + constexpr span_iterator& operator++() noexcept + { + base_type::operator++(); + return *this; + } + + constexpr span_iterator operator++(int) noexcept { return base_type::operator++(1); } + + constexpr span_iterator& operator--() noexcept + { + base_type::operator--(); + return *this; + } + + constexpr span_iterator operator--(int) noexcept { return base_type::operator--(1); } + + constexpr span_iterator operator+(difference_type n) const noexcept + { + return base_type::operator+(n); + } + + constexpr span_iterator& operator+=(difference_type n) noexcept + { + return base_type::operator+=(n); + } + + constexpr span_iterator operator-(difference_type n) const noexcept + { + return base_type::operator-(n); + } + + constexpr span_iterator& operator-=(difference_type n) noexcept + { + return base_type::operator-=(n); + } + + constexpr difference_type operator-(const span_iterator& rhs) const noexcept + { + return base_type::operator-(rhs); + } + + constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } + + constexpr bool operator==(const span_iterator& rhs) const noexcept + { + return base_type::operator==(rhs); + } + + constexpr bool operator!=(const span_iterator& rhs) const noexcept + { + return !(*this == rhs); + } + + constexpr bool operator<(const span_iterator& rhs) const noexcept + { + return base_type::operator<(rhs); + } + + constexpr bool operator<=(const span_iterator& rhs) const noexcept + { + return !(rhs < *this); + } + + constexpr bool operator>(const span_iterator& rhs) const noexcept { return rhs < *this; } + + constexpr bool operator>=(const span_iterator& rhs) const noexcept + { + return !(rhs > *this); + } + + void swap(span_iterator& rhs) noexcept { base_type::swap(rhs); } + }; + + template + constexpr const_span_iterator + operator+(typename const_span_iterator::difference_type n, + const const_span_iterator& rhs) noexcept + { + return rhs + n; } - constexpr reference operator*() const { Expects(span_); return (*span_)[index_]; } - constexpr pointer operator->() const { Expects(span_); return &((*span_)[index_]); } - - constexpr const_span_iterator& operator++() noexcept + template + constexpr const_span_iterator + operator-(typename const_span_iterator::difference_type n, + const const_span_iterator& rhs) noexcept { - Expects(span_ && index_ >= 0 && index_ < span_->length()); - ++index_; - return *this; + return rhs - n; } - constexpr const_span_iterator operator++(int) noexcept + template + constexpr span_iterator operator+(typename span_iterator::difference_type n, + const span_iterator& rhs) noexcept { - auto ret = *this; - ++(*this); - return ret; + return rhs + n; } - constexpr const_span_iterator& operator--() noexcept + template + constexpr span_iterator operator-(typename span_iterator::difference_type n, + const span_iterator& rhs) noexcept { - Expects(span_ && index_ > 0 && index_ <= span_->length()); - --index_; - return *this; + return rhs - n; } - constexpr const_span_iterator operator--(int) noexcept - { - auto ret = *this; - --(*this); - return ret; - } - - constexpr const_span_iterator operator+(difference_type n) const noexcept - { - auto ret{*this}; - return ret += n; - } - - constexpr const_span_iterator& operator+=(difference_type n) noexcept - { - Expects(span_ && (index_ + n) >= 0 && (index_ + n) <= span_->length()); - index_ += n; - return *this; - } - - constexpr const_span_iterator operator-(difference_type n) const noexcept - { - auto ret{*this}; - return ret -= n; - } - - constexpr const_span_iterator& operator-=(difference_type n) noexcept - { - return *this += -n; - } - - constexpr difference_type operator-(const const_span_iterator& rhs) const noexcept - { - Expects(span_ == rhs.span_); - return index_ - rhs.index_; - } - - constexpr reference operator[](difference_type n) const noexcept - { - return *(*this + n); - } - - constexpr bool operator==(const const_span_iterator& rhs) const noexcept - { - return span_ == rhs.span_ && index_ == rhs.index_; - } - - constexpr bool operator!=(const const_span_iterator& rhs) const noexcept { return !(*this == rhs); } - - constexpr bool operator<(const const_span_iterator& rhs) const noexcept - { - Expects(span_ == rhs.span_); - return index_ < rhs.index_; - } - - constexpr bool operator<=(const const_span_iterator& rhs) const noexcept { return !(rhs < *this); } - - constexpr bool operator>(const const_span_iterator& rhs) const noexcept { return rhs < *this; } - - constexpr bool operator>=(const const_span_iterator& rhs) const noexcept { return !(rhs > *this); } - - void swap(const_span_iterator& rhs) noexcept - { - std::swap(index_, rhs.index_); - std::swap(m_span, rhs.m_span); - } - -private: - const Span* span_; - ptrdiff_t index_; -}; - - -template -class span_iterator : public const_span_iterator -{ - using base_type = const_span_iterator; - -public: - using iterator_category = std::random_access_iterator_tag; - using value_type = typename Span::element_type; - using difference_type = std::ptrdiff_t; - - using pointer = value_type*; - using reference = value_type&; - - constexpr span_iterator() : base_type() {} - constexpr span_iterator(const Span* span, typename Span::index_type index) : base_type(span, index) {} - - constexpr reference operator*() const { return const_cast(base_type::operator*()); } - constexpr pointer operator->() const { return const_cast(base_type::operator->()); } - - constexpr span_iterator& operator++() noexcept { base_type::operator++(); return *this; } - - constexpr span_iterator operator++(int) noexcept { return base_type::operator++(1); } - - constexpr span_iterator& operator--() noexcept { base_type::operator--(); return *this; } - - constexpr span_iterator operator--(int) noexcept { return base_type::operator--(1); } - - constexpr span_iterator operator+(difference_type n) const noexcept { return base_type::operator+(n); } - - constexpr span_iterator& operator+=(difference_type n) noexcept { return base_type::operator+=(n); } - - constexpr span_iterator operator-(difference_type n) const noexcept { return base_type::operator-(n); } - - constexpr span_iterator& operator-=(difference_type n) noexcept { return base_type::operator-=(n); } - - constexpr difference_type operator-(const span_iterator& rhs) const noexcept { return base_type::operator-(rhs); } - - constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); } - - constexpr bool operator==(const span_iterator& rhs) const noexcept { return base_type::operator==(rhs); } - - constexpr bool operator!=(const span_iterator& rhs) const noexcept { return !(*this == rhs); } - - constexpr bool operator<(const span_iterator& rhs) const noexcept { return base_type::operator<(rhs); } - - constexpr bool operator<=(const span_iterator& rhs) const noexcept { return !(rhs < *this); } - - constexpr bool operator>(const span_iterator& rhs) const noexcept { return rhs < *this; } - - constexpr bool operator>=(const span_iterator& rhs) const noexcept { return !(rhs > *this); } - - void swap(span_iterator& rhs) noexcept { base_type::swap(rhs); } -}; - -template -constexpr const_span_iterator operator+(typename const_span_iterator::difference_type n, - const const_span_iterator& rhs) noexcept -{ - return rhs + n; -} - -template -constexpr const_span_iterator operator-(typename const_span_iterator::difference_type n, - const const_span_iterator& rhs) noexcept -{ - return rhs - n; -} - -template -constexpr span_iterator operator+(typename span_iterator::difference_type n, - const span_iterator& rhs) noexcept -{ - return rhs + n; -} - -template -constexpr span_iterator operator-(typename span_iterator::difference_type n, - const span_iterator& rhs) noexcept -{ - return rhs - n; -} - } // namespace details - -// [span], class template span +// [span], class template span template -class span { +class span +{ public: - // constants and types + // constants and types using element_type = ElementType; using index_type = std::ptrdiff_t; using pointer = element_type*; @@ -378,135 +428,140 @@ public: constexpr static const index_type extent = Extent; - // [span.cons], span constructors, copy, assignment, and destructor - constexpr span() noexcept : storage_(nullptr, extent_type<0>()) - {} + // [span.cons], span constructors, copy, assignment, and destructor + constexpr span() noexcept : storage_(nullptr, extent_type<0>()) {} - constexpr span(nullptr_t) noexcept : span() - {} + constexpr span(nullptr_t) noexcept : span() {} - constexpr span(pointer ptr, index_type count) : storage_(ptr, count) - {} + constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {} constexpr span(pointer firstElem, pointer lastElem) : storage_(firstElem, std::distance(firstElem, lastElem)) - {} - - template - constexpr span(element_type(&arr)[N]) noexcept - : storage_(&arr[0], extent_type()) - {} + { + } template - constexpr span(std::array& arr) noexcept - : storage_(&arr[0], extent_type()) - {} + constexpr span(element_type (&arr)[N]) noexcept : storage_(&arr[0], extent_type()) + { + } + + template + constexpr span(std::array& arr) noexcept : storage_(&arr[0], extent_type()) + { + } template ::value>> constexpr span(std::array, N>& arr) noexcept : storage_(&arr[0], extent_type()) - {} + { + } template ::value>> constexpr span(const std::array, N>& arr) noexcept : storage_(&arr[0], extent_type()) - {} + { + } // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. template ::value && - std::is_convertible::value && - std::is_convertible().data())>::value> - > - constexpr span(Container& cont) : span(cont.data(), cont.size()) {} + class = std::enable_if_t< + !details::is_span::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr span(Container& cont) : span(cont.data(), cont.size()) + { + } template ::value && - !details::is_span::value && - std::is_convertible::value && - std::is_convertible().data())>::value> - > - constexpr span(const Container& cont) : span(cont.data(), cont.size()) {} + class = std::enable_if_t< + std::is_const::value && !details::is_span::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr span(const Container& cont) : span(cont.data(), cont.size()) + { + } constexpr span(const span& other) noexcept = default; constexpr span(span&& other) noexcept = default; - template ::value && - details::is_allowed_element_type_conversion::value - > - > - constexpr span(const span& other) - : storage_(reinterpret_cast(other.data()), extent_type(other.size())) - {} - - template ::value && - details::is_allowed_element_type_conversion::value - > - > + details::is_allowed_element_type_conversion::value>> + constexpr span(const span& other) + : storage_(reinterpret_cast(other.data()), extent_type(other.size())) + { + } + + template < + class OtherElementType, std::ptrdiff_t OtherExtent, + class = std::enable_if_t< + details::is_allowed_extent_conversion::value && + details::is_allowed_element_type_conversion::value>> constexpr span(span&& other) : storage_(reinterpret_cast(other.data()), extent_type(other.size())) - {} + { + } ~span() noexcept = default; constexpr span& operator=(const span& other) noexcept = default; constexpr span& operator=(span&& other) noexcept = default; - // [span.sub], span subviews + // [span.sub], span subviews template constexpr span first() const { Expects(Count >= 0 && Count <= size()); - return { data(), Count }; + return {data(), Count}; } template constexpr span last() const { Expects(Count >= 0 && Count <= size()); - return{ data() + (size() - Count), Count }; + return {data() + (size() - Count), Count}; } template constexpr span subspan() const { Expects((Offset == 0 || Offset > 0 && Offset <= size()) && - (Count == dynamic_extent || Count >= 0 && Offset + Count <= size())); - return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count }; + (Count == dynamic_extent || Count >= 0 && Offset + Count <= size())); + return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; } constexpr span first(index_type count) const { Expects(count >= 0 && count <= size()); - return { data(), count }; + return {data(), count}; } constexpr span last(index_type count) const { Expects(count >= 0 && count <= size()); - return { data() + (size() - count), count }; + return {data() + (size() - count), count}; } constexpr span subspan(index_type offset, - index_type count = dynamic_extent) const + index_type count = dynamic_extent) const { Expects((offset == 0 || offset > 0 && offset <= size()) && - (count == dynamic_extent || count >= 0 && offset + count <= size())); - return { data() + offset, count == dynamic_extent ? size() - offset : count }; + (count == dynamic_extent || count >= 0 && offset + count <= size())); + return {data() + offset, count == dynamic_extent ? size() - offset : count}; } - // [span.obs], span observers + // [span.obs], span observers constexpr index_type length() const noexcept { return size(); } - constexpr index_type size() const noexcept { return storage_.size(); } + constexpr index_type size() const noexcept { return storage_.size(); } constexpr index_type length_bytes() const noexcept { return size_bytes(); } constexpr index_type size_bytes() const noexcept { return size() * sizeof(element_type); } constexpr bool empty() const noexcept { return size() == 0; } - // [span.elem], span element access + // [span.elem], span element access constexpr reference operator[](index_type idx) const { Expects(idx >= 0 && idx < storage_.size()); @@ -515,13 +570,13 @@ public: constexpr reference operator()(index_type idx) const { return this->operator[](idx); } constexpr pointer data() const noexcept { return storage_.data(); } - // [span.iter], span iterator support + // [span.iter], span iterator support iterator begin() const noexcept { return {this, 0}; } iterator end() const noexcept { return {this, length()}; } const_iterator cbegin() const noexcept { return {this, 0}; } const_iterator cend() const noexcept { return {this, length()}; } - + reverse_iterator rbegin() const noexcept { return reverse_iterator{{this, length()}}; } reverse_iterator rend() const noexcept { return reverse_iterator{{this, 0}}; } @@ -531,7 +586,7 @@ public: private: template class extent_type; - + template class extent_type { @@ -544,12 +599,11 @@ private: constexpr extent_type(extent_type ext) noexcept { static_assert(Other == Extent || Other == dynamic_extent, - "Mismatch between fixed-size extent and size of initializing data."); + "Mismatch between fixed-size extent and size of initializing data."); Expects(ext.size() == Extent); } - constexpr extent_type(index_type size) - { Expects(size == Extent); } + constexpr extent_type(index_type size) { Expects(size == Extent); } constexpr inline index_type size() const noexcept { return Extent; } }; @@ -560,19 +614,18 @@ private: public: template explicit constexpr extent_type(extent_type ext) : size_(ext.size()) - {} + { + } - explicit constexpr extent_type(index_type size) : size_(size) - { Expects(size >= 0); } + explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); } - constexpr inline index_type size() const noexcept - { return size_; } + constexpr inline index_type size() const noexcept { return size_; } private: index_type size_; }; - // this implementation detail class lets us take advantage of the + // this implementation detail class lets us take advantage of the // empty base class optimization to pay for only storage of a single // pointer in the case of fixed-size spans template @@ -580,12 +633,12 @@ private: { public: template - constexpr storage_type(pointer data, OtherExtentType ext) - : ExtentType(ext), data_(data) - { Expects((!data && size() == 0) || (data && size() >= 0)); } + constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + { + Expects((!data && size() == 0) || (data && size() >= 0)); + } - constexpr inline pointer data() const noexcept - { return data_; } + constexpr inline pointer data() const noexcept { return data_; } private: pointer data_; @@ -594,60 +647,81 @@ private: storage_type> storage_; }; - -// [span.comparison], span comparison operators +// [span.comparison], span comparison operators template -constexpr bool operator==(const span& l, const span& r) -{ return std::equal(l.begin(), l.end(), r.begin(), r.end()); } +constexpr bool operator==(const span& l, const span& r) +{ + return std::equal(l.begin(), l.end(), r.begin(), r.end()); +} template -constexpr bool operator!=(const span& l, const span& r) -{ return !(l == r); } +constexpr bool operator!=(const span& l, const span& r) +{ + return !(l == r); +} template -constexpr bool operator<(const span& l, const span& r) -{ return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); } +constexpr bool operator<(const span& l, const span& r) +{ + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +} template -constexpr bool operator<=(const span& l, const span& r) -{ return !(l > r); } +constexpr bool operator<=(const span& l, const span& r) +{ + return !(l > r); +} template -constexpr bool operator>(const span& l, const span& r) -{ return r < l; } +constexpr bool operator>(const span& l, const span& r) +{ + return r < l; +} template -constexpr bool operator>=(const span& l, const span& r) -{ return !(l < r); } - +constexpr bool operator>=(const span& l, const span& r) +{ + return !(l < r); +} namespace details { // if we only supported compilers with good constexpr support then // this pair of classes could collapse down to a constexpr function - // we should use a narrow_cast<> to go to size_t, but older compilers may not see it as constexpr + // we should use a narrow_cast<> to go to size_t, but older compilers may not see it as + // constexpr // and so will fail compilation of the template template - struct calculate_byte_size : - std::integral_constant(sizeof(ElementType) * static_cast(Extent))> - {}; + struct calculate_byte_size + : std::integral_constant(sizeof(ElementType) * + static_cast(Extent))> + { + }; template - struct calculate_byte_size : - std::integral_constant - {}; + struct calculate_byte_size + : std::integral_constant + { + }; } - -// [span.objectrep], views of object representation +// [span.objectrep], views of object representation template -span::value> as_bytes(span s) noexcept -{ return {reinterpret_cast(s.data()), s.size_bytes()}; } +span::value> +as_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} -template ::value>> -span::value> as_writeable_bytes(span s) noexcept -{ return {reinterpret_cast(s.data()), s.size_bytes()}; } +template ::value>> +span::value> +as_writeable_bytes(span s) noexcept +{ + return {reinterpret_cast(s.data()), s.size_bytes()}; +} } // namespace gsl diff --git a/include/string_span.h b/include/string_span.h index ccfe251..bef8288 100644 --- a/include/string_span.h +++ b/include/string_span.h @@ -36,8 +36,7 @@ // blanket turn off warnings from CppCoreCheck for now // so people aren't annoyed by them when running the tool. // more targeted suppressions will be added in a future update to the GSL -#pragma warning(disable: 26481 26482 26483 26485 26490 26491 26492 26493 26495) - +#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495) // VS 2013 workarounds #if _MSC_VER <= 1800 @@ -80,19 +79,19 @@ namespace gsl // (sometimes needlessly) break existing programs when introduced. // -template +template using basic_zstring = CharT*; -template +template using czstring = basic_zstring; -template +template using cwzstring = basic_zstring; -template +template using zstring = basic_zstring; -template +template using wzstring = basic_zstring; // @@ -103,85 +102,93 @@ using wzstring = basic_zstring; // // Will fail-fast if sentinel cannot be found before max elements are examined. // -template +template span ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) { auto cur = seq; while ((cur - seq) < max && *cur != Sentinel) ++cur; Ensures(*cur == Sentinel); - return{ seq, cur - seq }; + return {seq, cur - seq}; } - // // ensure_z - creates a span for a czstring or cwzstring. // Will fail fast if a null-terminator cannot be found before // the limit of size_type. // -template -inline span ensure_z(T* const & sz, std::ptrdiff_t max = PTRDIFF_MAX) +template +inline span ensure_z(T* const& sz, std::ptrdiff_t max = PTRDIFF_MAX) { return ensure_sentinel(sz, max); } -// TODO (neilmac) there is probably a better template-magic way to get the const and non-const overloads to share an implementation +// TODO (neilmac) there is probably a better template-magic way to get the const and non-const +// overloads to share an implementation inline span ensure_z(char* const& sz, std::ptrdiff_t max) { auto len = strnlen(sz, narrow_cast(max)); Ensures(sz[len] == 0); - return{ sz, static_cast(len) }; + return {sz, static_cast(len)}; } inline span ensure_z(const char* const& sz, std::ptrdiff_t max) { auto len = strnlen(sz, narrow_cast(max)); Ensures(sz[len] == 0); - return{ sz, static_cast(len) }; + return {sz, static_cast(len)}; } inline span ensure_z(wchar_t* const& sz, std::ptrdiff_t max) { auto len = wcsnlen(sz, narrow_cast(max)); Ensures(sz[len] == 0); - return{ sz, static_cast(len) }; + return {sz, static_cast(len)}; } inline span ensure_z(const wchar_t* const& sz, std::ptrdiff_t max) { auto len = wcsnlen(sz, narrow_cast(max)); Ensures(sz[len] == 0); - return{ sz, static_cast(len) }; + return {sz, static_cast(len)}; } -template -span ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], static_cast(N)); } +template +span ensure_z(T (&sz)[N]) +{ + return ensure_z(&sz[0], static_cast(N)); +} -template -span::type, dynamic_extent> ensure_z(Cont& cont) +template +span::type, dynamic_extent> +ensure_z(Cont& cont) { return ensure_z(cont.data(), static_cast(cont.length())); } -template +template class basic_string_span; namespace details { template struct is_basic_string_span_oracle : std::false_type - {}; + { + }; template struct is_basic_string_span_oracle> : std::true_type - {}; + { + }; template struct is_basic_string_span : is_basic_string_span_oracle> - {}; + { + }; template struct length_func - {}; + { + }; template <> struct length_func @@ -220,7 +227,6 @@ namespace details }; } - // // string_span and relatives // @@ -247,19 +253,17 @@ public: // copy constexpr basic_string_span(const basic_string_span& other) = default; - // move +// move #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_string_span(basic_string_span&& other) = default; #else - constexpr basic_string_span(basic_string_span&& other) - : span_(std::move(other.span_)) - {} + constexpr basic_string_span(basic_string_span&& other) : span_(std::move(other.span_)) {} #endif // assign constexpr basic_string_span& operator=(const basic_string_span& other) = default; - // move assign +// move assign #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_string_span& operator=(basic_string_span&& other) = default; #else @@ -271,211 +275,160 @@ public: #endif // from nullptr - constexpr basic_string_span(std::nullptr_t ptr) noexcept - : span_(ptr) - {} + constexpr basic_string_span(std::nullptr_t ptr) noexcept : span_(ptr) {} // from nullptr and length - constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept - : span_(ptr, length) - {} + constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept : span_(ptr, length) + { + } // From static arrays - if 0-terminated, remove 0 from the view // from static arrays and string literals - template - constexpr basic_string_span(value_type(&arr)[N]) noexcept - : span_(remove_z(arr)) - {} + template + constexpr basic_string_span(value_type (&arr)[N]) noexcept : span_(remove_z(arr)) + { + } // Those allow 0s within the length, so we do not remove them // from raw data and length - constexpr basic_string_span(pointer ptr, size_type length) noexcept - : span_(ptr, length) - {} + constexpr basic_string_span(pointer ptr, size_type length) noexcept : span_(ptr, length) {} // from string constexpr basic_string_span(std::string& s) noexcept : span_(const_cast(s.data()), narrow_cast(s.length())) - {} + { + } // from containers. Containers must have .size() and .data() function signatures template ::value - && !details::is_span::value - && std::is_convertible::value - && std::is_convertible().data())>::value> - > - constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size()) {} + typename = std::enable_if_t< + !details::is_basic_string_span::value && !details::is_span::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size()) + { + } // disallow creation from temporary containers and strings template ::value - && !details::is_span::value - && std::is_convertible::value - && std::is_convertible().data())>::value> - > - constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size()) {} + typename = std::enable_if_t< + !details::is_basic_string_span::value && !details::is_span::value && + std::is_convertible::value && + std::is_convertible().data())>::value>> + constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size()) + { + } #ifndef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE // from span template , impl_type>::value - > - > - constexpr basic_string_span(span other) noexcept - : span_(other) - {} + typename Dummy = std::enable_if_t< + std::is_convertible, impl_type>::value>> + constexpr basic_string_span(span other) noexcept : span_(other) + { + } #else // from span - constexpr basic_string_span(span other) noexcept - : span_(other) - {} - - template , value_type>::value>> + constexpr basic_string_span(span other) noexcept : span_(other) {} + + template , value_type>::value>> constexpr basic_string_span(span, Extent> other) noexcept : span_(other) - {} + { + } #endif // from string_span template ::impl_type, impl_type>::value - > - > + typename = std::enable_if_t::impl_type, impl_type>::value>> constexpr basic_string_span(basic_string_span other) noexcept : span_(other.data(), other.length()) - {} - - constexpr bool empty() const noexcept { - return length() == 0; } + constexpr bool empty() const noexcept { return length() == 0; } + // first Count elements - template + template constexpr basic_string_span first() const noexcept { - return{ span_.template first() }; + return {span_.template first()}; } constexpr basic_string_span first(size_type count) const noexcept { - return{ span_.first(count) }; + return {span_.first(count)}; } // last Count elements - template + template constexpr basic_string_span last() const noexcept { - return{ span_.template last() }; + return {span_.template last()}; } constexpr basic_string_span last(size_type count) const noexcept { - return{ span_.last(count) }; + return {span_.last(count)}; } // create a subview of Count elements starting from Offset - template + template constexpr basic_string_span subspan() const noexcept { - return{ span_.template subspan() }; + return {span_.template subspan()}; } - constexpr basic_string_span subspan(size_type offset, size_type count = dynamic_extent) const noexcept + constexpr basic_string_span + subspan(size_type offset, size_type count = dynamic_extent) const noexcept { - return{ span_.subspan(offset, count) }; + return {span_.subspan(offset, count)}; } - constexpr reference operator[](size_type idx) const noexcept - { - return span_[idx]; - } + constexpr reference operator[](size_type idx) const noexcept { return span_[idx]; } - constexpr pointer data() const noexcept - { - return span_.data(); - } + constexpr pointer data() const noexcept { return span_.data(); } // length of the span in elements - constexpr size_type length() const noexcept - { - return span_.size(); - } + constexpr size_type length() const noexcept { return span_.size(); } // length of the span in elements - constexpr size_type size() const noexcept - { - return span_.size(); - } + constexpr size_type size() const noexcept { return span_.size(); } // length of the span in bytes - constexpr size_type size_bytes() const noexcept - { - return span_.size_bytes(); - } + constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); } // length of the span in bytes - constexpr size_type length_bytes() const noexcept - { - return span_.length_bytes(); - } + constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); } - constexpr iterator begin() const noexcept - { - return span_.begin(); - } + constexpr iterator begin() const noexcept { return span_.begin(); } - constexpr iterator end() const noexcept - { - return span_.end(); - } + constexpr iterator end() const noexcept { return span_.end(); } - constexpr const_iterator cbegin() const noexcept - { - return span_.cbegin(); - } + constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); } - constexpr const_iterator cend() const noexcept - { - return span_.cend(); - } + constexpr const_iterator cend() const noexcept { return span_.cend(); } - constexpr reverse_iterator rbegin() const noexcept - { - return span_.rbegin(); - } + constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); } - constexpr reverse_iterator rend() const noexcept - { - return span_.rend(); - } + constexpr reverse_iterator rend() const noexcept { return span_.rend(); } - constexpr const_reverse_iterator crbegin() const noexcept - { - return span_.crbegin(); - } + constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); } - constexpr const_reverse_iterator crend() const noexcept - { - return span_.crend(); - } + constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); } private: - static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) noexcept { - return{ sz, details::length_func()(sz, max)}; + return {sz, details::length_func()(sz, max)}; } - template - static impl_type remove_z(value_type(&sz)[N]) noexcept + template + static impl_type remove_z(value_type (&sz)[N]) noexcept { return remove_z(&sz[0], narrow_cast(N)); } @@ -483,16 +436,16 @@ private: impl_type span_; }; -template +template using string_span = basic_string_span; -template +template using cstring_span = basic_string_span; -template +template using wstring_span = basic_string_span; -template +template using cwstring_span = basic_string_span; // @@ -500,39 +453,40 @@ using cwstring_span = basic_string_span; // #ifndef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG -template -std::basic_string::type> to_string(basic_string_span view) +template +std::basic_string::type> +to_string(basic_string_span view) { - return{ view.data(), static_cast(view.length()) }; + return {view.data(), static_cast(view.length())}; } #else inline std::string to_string(cstring_span<> view) { - return{ view.data(), static_cast(view.length()) }; + return {view.data(), static_cast(view.length())}; } inline std::string to_string(string_span<> view) { - return{ view.data(), static_cast(view.length()) }; + return {view.data(), static_cast(view.length())}; } inline std::wstring to_string(cwstring_span<> view) { - return{ view.data(), static_cast(view.length()) }; + return {view.data(), static_cast(view.length())}; } inline std::wstring to_string(wstring_span<> view) { - return{ view.data(), static_cast(view.length()) }; + return {view.data(), static_cast(view.length())}; } #endif // zero-terminated string span, used to convert // zero-terminated spans to legacy strings -template +template class basic_zstring_span { public: @@ -548,8 +502,7 @@ public: using impl_type = span; using string_span_type = basic_string_span; - constexpr basic_zstring_span(impl_type s) noexcept - : span_(s) + constexpr basic_zstring_span(impl_type s) noexcept : span_(s) { // expects a zero-terminated span Expects(s[s.size() - 1] == '\0'); @@ -558,19 +511,17 @@ public: // copy constexpr basic_zstring_span(const basic_zstring_span& other) = default; - // move +// move #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_zstring_span(basic_zstring_span&& other) = default; #else - constexpr basic_zstring_span(basic_zstring_span&& other) - : span_(std::move(other.span_)) - {} + constexpr basic_zstring_span(basic_zstring_span&& other) : span_(std::move(other.span_)) {} #endif // assign constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default; - // move assign +// move assign #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; #else @@ -583,7 +534,10 @@ public: constexpr bool empty() const noexcept { return span_.size() == 0; } - constexpr string_span_type as_string_span() const noexcept { return span_.first(span_.size()-1); } + constexpr string_span_type as_string_span() const noexcept + { + return span_.first(span_.size() - 1); + } constexpr string_span_type ensure_z() const noexcept { return gsl::ensure_z(span_); } @@ -609,9 +563,8 @@ using cwzstring_span = basic_zstring_span; // operator == template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator==(gsl::basic_string_span one, const T& other) noexcept { gsl::basic_string_span, Extent> tmp(other); @@ -622,11 +575,11 @@ bool operator==(gsl::basic_string_span one, const T& other) noexc #endif } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator==(const T& one, gsl::basic_string_span other) noexcept { gsl::basic_string_span, Extent> tmp(one); @@ -637,33 +590,33 @@ bool operator==(const T& one, gsl::basic_string_span other) noexc #endif } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator==(gsl::basic_string_span one, const T& other) noexcept { gsl::basic_string_span, Extent> tmp(other); return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator==(const T& one, gsl::basic_string_span other) noexcept { gsl::basic_string_span, Extent> tmp(one); @@ -673,50 +626,49 @@ bool operator==(const T& one, gsl::basic_string_span other) noexc // operator != template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator!=(gsl::basic_string_span one, const T& other) noexcept { return !(one == other); } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator!=(const T& one, gsl::basic_string_span other) noexcept { return !(one == other); } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator!=(gsl::basic_string_span one, const T& other) noexcept { return !(one == other); } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator!=(const T& one, gsl::basic_string_span other) noexcept { return !(one == other); @@ -725,53 +677,52 @@ bool operator!=(const T& one, gsl::basic_string_span other) noexc // operator< template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator<(gsl::basic_string_span one, const T& other) noexcept { gsl::basic_string_span, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator<(const T& one, gsl::basic_string_span other) noexcept { gsl::basic_string_span, Extent> tmp(one); return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator<(gsl::basic_string_span one, const T& other) noexcept { gsl::basic_string_span, Extent> tmp(other); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator<(const T& one, gsl::basic_string_span other) noexcept { gsl::basic_string_span, Extent> tmp(one); @@ -781,50 +732,49 @@ bool operator<(const T& one, gsl::basic_string_span other) noexce // operator <= template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator<=(gsl::basic_string_span one, const T& other) noexcept { return !(other < one); } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator<=(const T& one, gsl::basic_string_span other) noexcept { return !(other < one); } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator<=(gsl::basic_string_span one, const T& other) noexcept { return !(other < one); } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator<=(const T& one, gsl::basic_string_span other) noexcept { return !(other < one); @@ -833,50 +783,49 @@ bool operator<=(const T& one, gsl::basic_string_span other) noexc // operator> template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator>(gsl::basic_string_span one, const T& other) noexcept { return other < one; } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator>(const T& one, gsl::basic_string_span other) noexcept { return other < one; } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator>(gsl::basic_string_span one, const T& other) noexcept { return other < one; } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator>(const T& one, gsl::basic_string_span other) noexcept { return other < one; @@ -885,50 +834,49 @@ bool operator>(const T& one, gsl::basic_string_span other) noexce // operator >= template , Extent>>::value> -> + typename = std::enable_if_t, Extent>>::value>> bool operator>=(gsl::basic_string_span one, const T& other) noexcept { return !(one < other); } -template , Extent>>::value - && !gsl::details::is_basic_string_span::value> -> + std::is_convertible, Extent>>::value && + !gsl::details::is_basic_string_span::value>> bool operator>=(const T& one, gsl::basic_string_span other) noexcept { return !(one < other); } -#ifndef _MSC_VER +#ifndef _MSC_VER // VS treats temp and const containers as convertible to basic_string_span, // so the cases below are already covered by the previous operators -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator>=(gsl::basic_string_span one, const T& other) noexcept { return !(one < other); } -template ::value - && !gsl::details::is_basic_string_span::value - && std::is_convertible::value - && std::is_same().size(), *std::declval().data())>, DataType>::value> -> + !gsl::details::is_span::value && !gsl::details::is_basic_string_span::value && + std::is_convertible::value && + std::is_same().size(), *std::declval().data())>, + DataType>::value>> bool operator>=(const T& one, gsl::basic_string_span other) noexcept { return !(one < other);