1
0
mirror of https://github.com/microsoft/GSL.git synced 2025-03-30 08:19:45 -04:00

Applied clang-format to the source.

This commit is contained in:
Neil MacIntosh 2016-07-20 13:17:47 -07:00
parent ca4cdd80de
commit b03b04bfcd
8 changed files with 964 additions and 893 deletions

@ -16,6 +16,6 @@ AllowShortLoopsOnASingleLine: true
PointerAlignment: Left PointerAlignment: Left
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
AlignTrailingComments: false AlignTrailingComments: true
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true

@ -1,17 +1,17 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 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 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#pragma once #pragma once
@ -19,39 +19,38 @@
#ifndef GSL_GSL_H #ifndef GSL_GSL_H
#define GSL_GSL_H #define GSL_GSL_H
#include "gsl_assert.h" // Ensures/Expects #include "gsl_assert.h" // Ensures/Expects
#include "gsl_util.h" // finally()/narrow()/narrow_cast()... #include "gsl_util.h" // finally()/narrow()/narrow_cast()...
#include "span.h" // span #include "multi_span.h" // multi_span, strided_span...
#include "multi_span.h" // multi_span, strided_span... #include "span.h" // span
#include "string_span.h" // zstring, string_span, zstring_builder... #include "string_span.h" // zstring, string_span, zstring_builder...
#include <memory> #include <memory>
#ifdef _MSC_VER #ifdef _MSC_VER
// No MSVC does constexpr fully yet // No MSVC does constexpr fully yet
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr #define constexpr
// MSVC 2013 workarounds // MSVC 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept #define noexcept
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(push) #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 <= 1800
#endif // _MSC_VER #endif // _MSC_VER
namespace gsl namespace gsl
{ {
// //
// GSL.owner: ownership pointers // GSL.owner: ownership pointers
// //
using std::unique_ptr; using std::unique_ptr;
using std::shared_ptr; using std::shared_ptr;
@ -59,67 +58,74 @@ using std::shared_ptr;
template <class T> template <class T>
using owner = T; using owner = T;
// //
// not_null // not_null
// //
// Restricts a pointer or smart pointer to only hold non-null values. // Restricts a pointer or smart pointer to only hold non-null values.
// //
// Has zero size overhead over T. // Has zero size overhead over T.
// //
// If T is a pointer (i.e. T == U*) then // If T is a pointer (i.e. T == U*) then
// - allow construction from U* or U& // - allow construction from U* or U&
// - disallow construction from nullptr_t // - disallow construction from nullptr_t
// - disallow default construction // - disallow default construction
// - ensure construction from U* fails with nullptr // - ensure construction from U* fails with nullptr
// - allow implicit conversion to U* // - allow implicit conversion to U*
// //
template<class T> template <class T>
class not_null class not_null
{ {
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr."); static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public: public:
not_null(T t) : ptr_(t) { ensure_invariant(); } 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(const not_null& other) = default;
not_null& operator=(const not_null &other) = default; not_null& operator=(const not_null& other) = default;
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null(const not_null<U> &other) not_null(const not_null<U>& other)
{ {
*this = other; *this = other;
} }
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>> template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null& operator=(const not_null<U> &other) not_null& operator=(const not_null<U>& other)
{ {
ptr_ = other.get(); ptr_ = other.get();
return *this; 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(std::nullptr_t) = delete;
not_null(int) = delete; not_null(int) = delete;
not_null<T>& operator=(std::nullptr_t) = delete; not_null<T>& operator=(std::nullptr_t) = delete;
not_null<T>& operator=(int) = delete; not_null<T>& operator=(int) = delete;
T get() const { T get() const
{
#ifdef _MSC_VER #ifdef _MSC_VER
__assume(ptr_ != nullptr); __assume(ptr_ != nullptr);
#endif #endif
return ptr_; return ptr_;
} // the assume() should help the optimizer } // the assume() should help the optimizer
operator T() const { return get(); } operator T() const { return get(); }
T operator->() const { return get(); } T operator->() const { return get(); }
bool operator==(const T& rhs) const { return ptr_ == rhs; } 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 !(*this == rhs); }
private: private:
T ptr_; 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 // if not, we could make them optional via conditional compilation
void ensure_invariant() const { Expects(ptr_ != nullptr); } void ensure_invariant() const { Expects(ptr_ != nullptr); }
@ -139,14 +145,11 @@ private:
namespace std namespace std
{ {
template<class T> template <class T>
struct hash<gsl::not_null<T>> struct hash<gsl::not_null<T>>
{ {
size_t operator()(const gsl::not_null<T> & value) const size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
{ };
return hash<T>{}(value);
}
};
} // namespace std } // namespace std
@ -159,7 +162,7 @@ namespace std
#undef noexcept #undef noexcept
#pragma pop_macro("noexcept") #pragma pop_macro("noexcept")
#pragma warning(pop) #pragma warning(pop)
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800

@ -1,17 +1,17 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 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 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#pragma once #pragma once
@ -28,50 +28,50 @@
// //
// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default) // 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 // 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)) #if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ \
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif #endif
#define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
// //
// GSL.assert: assertions // GSL.assert: assertions
// //
namespace gsl 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) #if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define Expects(cond) if (!(cond)) \ #define Expects(cond) \
throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)); if (!(cond)) \
#define Ensures(cond) if (!(cond)) \ throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
throw gsl::fail_fast("GSL: Postcondition 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) #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define Expects(cond) \
#define Expects(cond) if (!(cond)) std::terminate(); if (!(cond)) std::terminate();
#define Ensures(cond) if (!(cond)) std::terminate(); #define Ensures(cond) \
if (!(cond)) std::terminate();
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define Expects(cond) #define Expects(cond)
#define Ensures(cond) #define Ensures(cond)
#endif
#endif
#endif // GSL_CONTRACTS_H #endif // GSL_CONTRACTS_H

@ -1,17 +1,17 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Copyright (c) 2015 Microsoft Corporation. All rights reserved. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// //
// This code is licensed under the MIT License (MIT). // This code is licensed under the MIT License (MIT).
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // 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 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#pragma once #pragma once
@ -26,11 +26,11 @@
// constexpr is not understood // constexpr is not understood
#pragma push_macro("constexpr") #pragma push_macro("constexpr")
#define constexpr #define constexpr
// noexcept is not understood // noexcept is not understood
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept #define noexcept
#endif // _MSC_VER <= 1800 #endif // _MSC_VER <= 1800
@ -38,54 +38,76 @@
namespace gsl namespace gsl
{ {
// This is a simple definition for now that allows // This is a simple definition for now that allows
// use of byte within span<> to be standards-compliant // use of byte within span<> to be standards-compliant
enum class byte : unsigned char {}; enum class byte : unsigned char
{
};
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
{ return b = byte(static_cast<unsigned char>(b) << shift); } {
return b = byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator<<(byte b, IntegerType shift) noexcept constexpr byte operator<<(byte b, IntegerType shift) noexcept
{ return byte(static_cast<unsigned char>(b) << shift); } {
return byte(static_cast<unsigned char>(b) << shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
{ return b = byte(static_cast<unsigned char>(b) >> shift); } {
return b = byte(static_cast<unsigned char>(b) >> shift);
}
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr byte operator>> (byte b, IntegerType shift) noexcept constexpr byte operator>>(byte b, IntegerType shift) noexcept
{ return byte(static_cast<unsigned char>(b) >> shift); } {
return byte(static_cast<unsigned char>(b) >> shift);
}
constexpr byte& operator|=(byte& l, byte r) noexcept constexpr byte& operator|=(byte& l, byte r) noexcept
{ return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); } {
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
}
constexpr byte operator|(byte l, byte r) noexcept constexpr byte operator|(byte l, byte r) noexcept
{ return byte(static_cast<unsigned char>(l) + static_cast<unsigned char>(r)); } {
return byte(static_cast<unsigned char>(l) + static_cast<unsigned char>(r));
}
constexpr byte& operator&=(byte& l, byte r) noexcept constexpr byte& operator&=(byte& l, byte r) noexcept
{ return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); } {
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte operator&(byte l, byte r) noexcept constexpr byte operator&(byte l, byte r) noexcept
{ return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); } {
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
}
constexpr byte& operator^=(byte& l, byte r) noexcept constexpr byte& operator^=(byte& l, byte r) noexcept
{ return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); } {
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
constexpr byte operator^(byte l, byte r) noexcept }
{ return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); }
constexpr byte operator~(byte b) noexcept
{ return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>> constexpr byte operator^(byte l, byte r) noexcept
constexpr IntegerType to_integer(byte b) noexcept { return {b}; } {
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
}
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
constexpr IntegerType to_integer(byte b) noexcept
{
return {b};
}
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800

@ -19,11 +19,11 @@
#ifndef GSL_UTIL_H #ifndef GSL_UTIL_H
#define GSL_UTIL_H #define GSL_UTIL_H
#include "gsl_assert.h" // Ensures/Expects #include "gsl_assert.h" // Ensures/Expects
#include <array> #include <array>
#include <utility>
#include <type_traits>
#include <exception> #include <exception>
#include <type_traits>
#include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -32,7 +32,7 @@
#define constexpr #define constexpr
#pragma warning(push) #pragma warning(push)
#pragma warning(disable: 4127) // conditional expression is constant #pragma warning(disable : 4127) // conditional expression is constant
// MSVC 2013 workarounds // MSVC 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
@ -42,13 +42,12 @@
// turn off some misguided warnings // turn off some misguided warnings
#pragma warning(push) #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 <= 1800
#endif // _MSC_VER #endif // _MSC_VER
namespace gsl namespace gsl
{ {
// //
@ -60,18 +59,20 @@ template <class F>
class final_act class final_act
{ {
public: public:
explicit final_act(F f) noexcept explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {}
: f_(std::move(f)), invoke_(true)
{}
final_act(final_act&& other) noexcept final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
: f_(std::move(other.f_)), invoke_(other.invoke_) {
{ other.invoke_ = false; } other.invoke_ = false;
}
final_act(const final_act&) = delete; final_act(const final_act&) = delete;
final_act& operator=(const final_act&) = delete; final_act& operator=(const final_act&) = delete;
~final_act() noexcept { if (invoke_) f_(); } ~final_act() noexcept
{
if (invoke_) f_();
}
private: private:
F f_; F f_;
@ -80,35 +81,44 @@ private:
// finally() - convenience function to generate a final_act // finally() - convenience function to generate a final_act
template <class F> template <class F>
inline final_act<F> finally(const F &f) inline final_act<F> finally(const F& f) noexcept
noexcept { return final_act<F>(f); } {
return final_act<F>(f);
}
template <class F> template <class F>
inline final_act<F> finally(F &&f) noexcept inline final_act<F> finally(F&& f) noexcept
{ return final_act<F>(std::forward<F>(f)); } {
return final_act<F>(std::forward<F>(f));
}
// narrow_cast(): a searchable way to do narrowing casts of values // narrow_cast(): a searchable way to do narrowing casts of values
template<class T, class U> template <class T, class U>
inline constexpr T narrow_cast(U u) noexcept inline constexpr T narrow_cast(U u) noexcept
{ return static_cast<T>(u); } {
return static_cast<T>(u);
}
struct narrowing_error : public std::exception {}; struct narrowing_error : public std::exception
{
};
namespace details namespace details
{ {
template<class T, class U> template <class T, class U>
struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> struct is_same_signedness
{}; : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
{
};
} }
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value // narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template<class T, class U> template <class T, class U>
inline T narrow(U u) inline T narrow(U u)
{ {
T t = narrow_cast<T>(u); T t = narrow_cast<T>(u);
if (static_cast<U>(t) != u) if (static_cast<U>(t) != u) throw narrowing_error();
throw narrowing_error(); #pragma warning(suppress : 4127) // suppress warning from MSVC compiler about constant in if-test
#pragma warning(suppress:4127) // suppress warning from MSVC compiler about constant in if-test
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{}))) if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
throw narrowing_error(); throw narrowing_error();
return t; return t;
@ -118,24 +128,35 @@ inline T narrow(U u)
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector // at() - Bounds-checked way of accessing static arrays, std::array, std::vector
// //
template <class T, size_t N> template <class T, size_t N>
constexpr T& at(T(&arr)[N], size_t index) constexpr T& at(T (&arr)[N], size_t index)
{ Expects(index < N); return arr[index]; } {
Expects(index < N);
return arr[index];
}
template <class T, size_t N> template <class T, size_t N>
constexpr T& at(std::array<T, N>& arr, size_t index) constexpr T& at(std::array<T, N>& arr, size_t index)
{ Expects(index < N); return arr[index]; } {
Expects(index < N);
return arr[index];
}
template <class Cont> template <class Cont>
constexpr typename Cont::value_type& at(Cont& cont, size_t index) 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 <class T> template <class T>
constexpr const T& at(std::initializer_list<T> cont, size_t index) constexpr const T& at(std::initializer_list<T> cont, size_t index)
{ Expects(index < cont.size()); return *(cont.begin() + index); } {
Expects(index < cont.size());
return *(cont.begin() + index);
}
} // namespace gsl } // namespace gsl
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)

@ -20,8 +20,8 @@
#define GSL_MULTI_SPAN_H #define GSL_MULTI_SPAN_H
#include "gsl_assert.h" #include "gsl_assert.h"
#include "gsl_util.h"
#include "gsl_byte.h" #include "gsl_byte.h"
#include "gsl_util.h"
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cassert> #include <cassert>
@ -52,7 +52,7 @@
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG #define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
#define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT #define GSL_MSVC_NO_SUPPORT_FOR_MOVE_CTOR_DEFAULT
// noexcept is not understood // noexcept is not understood
#ifndef GSL_THROW_ON_CONTRACT_VIOLATION #ifndef GSL_THROW_ON_CONTRACT_VIOLATION
#pragma push_macro("noexcept") #pragma push_macro("noexcept")
#define noexcept /* nothing */ #define noexcept /* nothing */
@ -217,10 +217,7 @@ public:
return ret; return ret;
} }
friend constexpr index operator*(value_type v, const index& rhs) noexcept friend constexpr index operator*(value_type v, const index& rhs) noexcept { return rhs * v; }
{
return rhs * v;
}
constexpr index& operator*=(value_type v) noexcept constexpr index& operator*=(value_type v) noexcept
{ {
@ -743,8 +740,7 @@ public:
} }
constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept
: m_extents(extents), : m_extents(extents), m_strides(strides)
m_strides(strides)
{ {
} }
@ -841,8 +837,7 @@ public:
using index_size_type = typename IndexType::value_type; using index_size_type = typename IndexType::value_type;
template <typename Bounds> template <typename Bounds>
explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept
: boundary_(bnd.index_bounds()), : boundary_(bnd.index_bounds()), curr_(std::move(curr))
curr_(std::move(curr))
{ {
static_assert(is_bounds<Bounds>::value, "Bounds type must be provided"); static_assert(is_bounds<Bounds>::value, "Bounds type must be provided");
} }
@ -930,7 +925,7 @@ public:
return ret -= n; 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 constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
{ {
@ -1137,7 +1132,7 @@ namespace details
template <typename T, typename Arg, typename... Args> template <typename T, typename Arg, typename... Args>
std::enable_if_t< std::enable_if_t<
!std::is_same<Arg, dim<dynamic_range>>::value && !std::is_same<Arg, Sep>::value, T> !std::is_same<Arg, dim<dynamic_range>>::value && !std::is_same<Arg, Sep>::value, T>
static_as_span_helper(Arg, Args... args) static_as_span_helper(Arg, Args... args)
{ {
return static_as_span_helper<T>(args...); return static_as_span_helper<T>(args...);
} }
@ -1159,7 +1154,8 @@ namespace details
}; };
template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions> template <typename ValueType, std::ptrdiff_t FirstDimension, std::ptrdiff_t... RestDimensions>
struct is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>> : std::true_type struct is_multi_span_oracle<multi_span<ValueType, FirstDimension, RestDimensions...>>
: std::true_type
{ {
}; };
@ -1249,11 +1245,13 @@ public:
constexpr multi_span(value_type&&) = delete; constexpr multi_span(value_type&&) = delete;
// construct from pointer + length // 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 // construct from pointer + length - multidimensional
constexpr multi_span(pointer data, bounds_type bounds) noexcept : data_(data), constexpr multi_span(pointer data, bounds_type bounds) noexcept
bounds_(std::move(bounds)) : data_(data), bounds_(std::move(bounds))
{ {
Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0); Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0);
} }
@ -1263,7 +1261,8 @@ public:
typename = std::enable_if_t<std::is_convertible<Ptr, pointer>::value && typename = std::enable_if_t<std::is_convertible<Ptr, pointer>::value &&
details::LessThan<bounds_type::dynamic_rank, 2>::value>> details::LessThan<bounds_type::dynamic_rank, 2>::value>>
constexpr multi_span(pointer begin, Ptr end) constexpr multi_span(pointer begin, Ptr end)
: multi_span(begin, details::newBoundsHelper<bounds_type>(static_cast<pointer>(end) - begin)) : multi_span(begin,
details::newBoundsHelper<bounds_type>(static_cast<pointer>(end) - begin))
{ {
Expects(begin != nullptr && end != nullptr && begin <= static_cast<pointer>(end)); Expects(begin != nullptr && end != nullptr && begin <= static_cast<pointer>(end));
} }
@ -1273,9 +1272,8 @@ public:
constexpr multi_span(T (&arr)[N]) constexpr multi_span(T (&arr)[N])
: multi_span(reinterpret_cast<pointer>(arr), bounds_type{typename Helper::bounds_type{}}) : multi_span(reinterpret_cast<pointer>(arr), bounds_type{typename Helper::bounds_type{}})
{ {
static_assert( static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
std::is_convertible<typename Helper::value_type(*) [], value_type(*) []>::value, "Cannot convert from source type to target multi_span type.");
"Cannot convert from source type to target multi_span type.");
static_assert(std::is_convertible<typename Helper::bounds_type, bounds_type>::value, static_assert(std::is_convertible<typename Helper::bounds_type, bounds_type>::value,
"Cannot construct a multi_span from an array with fewer elements."); "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) constexpr multi_span(T* const& data, size_type size)
: multi_span(reinterpret_cast<pointer>(data), typename Helper::bounds_type{size}) : multi_span(reinterpret_cast<pointer>(data), typename Helper::bounds_type{size})
{ {
static_assert( static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
std::is_convertible<typename Helper::value_type(*) [], value_type(*) []>::value, "Cannot convert from source type to target multi_span type.");
"Cannot convert from source type to target multi_span type.");
} }
// construct from std::array // construct from std::array
template <typename T, size_t N> template <typename T, size_t N>
constexpr multi_span(std::array<T, N>& arr) : multi_span(arr.data(), bounds_type{static_bounds<N>{}}) constexpr multi_span(std::array<T, N>& arr)
: multi_span(arr.data(), bounds_type{static_bounds<N>{}})
{ {
static_assert( static_assert(
std::is_convertible<T(*) [], typename std::remove_const_t<value_type>(*) []>::value, std::is_convertible<T(*)[], typename std::remove_const_t<value_type>(*)[]>::value,
"Cannot convert from source type to target multi_span type."); "Cannot convert from source type to target multi_span type.");
static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value, static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
"You cannot construct a multi_span from a std::array of smaller size."); "You cannot construct a multi_span from a std::array of smaller size.");
@ -1307,7 +1305,7 @@ public:
constexpr multi_span(const std::array<std::remove_const_t<value_type>, N>& arr) constexpr multi_span(const std::array<std::remove_const_t<value_type>, N>& arr)
: multi_span(arr.data(), static_bounds<N>()) : multi_span(arr.data(), static_bounds<N>())
{ {
static_assert(std::is_convertible<T(*) [], std::remove_const_t<value_type>>::value, static_assert(std::is_convertible<T(*)[], std::remove_const_t<value_type>>::value,
"Cannot convert from source type to target multi_span type."); "Cannot convert from source type to target multi_span type.");
static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value, static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
"You cannot construct a multi_span from a std::array of smaller size."); "You cannot construct a multi_span from a std::array of smaller size.");
@ -1329,7 +1327,7 @@ public:
DataType>::value>> DataType>::value>>
constexpr multi_span(Cont& cont) constexpr multi_span(Cont& cont)
: multi_span(static_cast<pointer>(cont.data()), : multi_span(static_cast<pointer>(cont.data()),
details::newBoundsHelper<bounds_type>(narrow_cast<size_type>(cont.size()))) details::newBoundsHelper<bounds_type>(narrow_cast<size_type>(cont.size())))
{ {
} }
@ -1348,8 +1346,8 @@ public:
typename OtherBounds = static_bounds<OtherDimensions...>, typename OtherBounds = static_bounds<OtherDimensions...>,
typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value && typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value &&
std::is_convertible<OtherBounds, bounds_type>::value>> std::is_convertible<OtherBounds, bounds_type>::value>>
constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) noexcept : data_(other.data_), constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) noexcept
bounds_(other.bounds_) : data_(other.data_), bounds_(other.bounds_)
{ {
} }
@ -1424,7 +1422,8 @@ public:
// subspan() - create a subview of count elements starting at offset // subspan() - create a subview of count elements starting at offset
// supplying dynamic_range for count will consume all available elements from offset // supplying dynamic_range for count will consume all available elements from offset
constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset, constexpr multi_span<ValueType, dynamic_range> subspan(size_type offset,
size_type count = dynamic_range) const noexcept size_type count = dynamic_range) const
noexcept
{ {
Expects((offset >= 0 && offset <= this->size()) && Expects((offset >= 0 && offset <= this->size()) &&
(count == dynamic_range || (count <= this->size() - offset))); (count == dynamic_range || (count <= this->size() - offset)));
@ -1535,7 +1534,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator==(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return bounds_.size() == other.bounds_.size() && return bounds_.size() == other.bounds_.size() &&
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin())); (data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
@ -1544,7 +1544,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator!=(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return !(*this == other); return !(*this == other);
} }
@ -1552,7 +1553,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator<(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end()); return std::lexicographical_compare(this->begin(), this->end(), other.begin(), other.end());
} }
@ -1560,7 +1562,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator<=(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return !(other < *this); return !(other < *this);
} }
@ -1568,7 +1571,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator>(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return (other < *this); return (other < *this);
} }
@ -1576,7 +1580,8 @@ public:
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions, template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
typename Dummy = std::enable_if_t<std::is_same< typename Dummy = std::enable_if_t<std::is_same<
std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>> std::remove_cv_t<value_type>, std::remove_cv_t<OtherValueType>>::value>>
constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const noexcept constexpr bool operator>=(const multi_span<OtherValueType, OtherDimensions...>& other) const
noexcept
{ {
return !(*this < other); return !(*this < other);
} }
@ -1590,8 +1595,8 @@ public:
// DimCount and Enabled here are workarounds for a bug in MSVC 2015 // DimCount and Enabled here are workarounds for a bug in MSVC 2015
template <typename SpanType, typename... Dimensions2, size_t DimCount = sizeof...(Dimensions2), template <typename SpanType, typename... Dimensions2, size_t DimCount = sizeof...(Dimensions2),
bool Enabled = (DimCount > 0), typename = std::enable_if_t<Enabled>> bool Enabled = (DimCount > 0), typename = std::enable_if_t<Enabled>>
constexpr multi_span<typename SpanType::value_type, Dimensions2::value...> as_span(SpanType s, constexpr multi_span<typename SpanType::value_type, Dimensions2::value...>
Dimensions2... dims) as_span(SpanType s, Dimensions2... dims)
{ {
static_assert(details::is_multi_span<SpanType>::value, static_assert(details::is_multi_span<SpanType>::value,
"Variadic as_span() is for reshaping existing spans."); "Variadic as_span() is for reshaping existing spans.");
@ -1628,13 +1633,13 @@ multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) noexcept
// on all implementations. It should be considered an experimental extension // on all implementations. It should be considered an experimental extension
// to the standard GSL interface. // to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions> template <typename U, std::ptrdiff_t... Dimensions>
constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept -> multi_span<
-> multi_span<const U, static_cast<std::ptrdiff_t>( const U, static_cast<std::ptrdiff_t>(
multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range
? (static_cast<size_t>( ? (static_cast<size_t>(
multi_span<const byte, Dimensions...>::bounds_type::static_size) / multi_span<const byte, Dimensions...>::bounds_type::static_size) /
sizeof(U)) sizeof(U))
: dynamic_range)> : dynamic_range)>
{ {
using ConstByteSpan = multi_span<const byte, Dimensions...>; using ConstByteSpan = multi_span<const byte, Dimensions...>;
static_assert( static_assert(
@ -1653,12 +1658,13 @@ constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept
// on all implementations. It should be considered an experimental extension // on all implementations. It should be considered an experimental extension
// to the standard GSL interface. // to the standard GSL interface.
template <typename U, std::ptrdiff_t... Dimensions> template <typename U, std::ptrdiff_t... Dimensions>
constexpr auto as_span(multi_span<byte, Dimensions...> s) noexcept -> multi_span< constexpr auto as_span(multi_span<byte, Dimensions...> s) noexcept
U, narrow_cast<std::ptrdiff_t>( -> multi_span<U, narrow_cast<std::ptrdiff_t>(
multi_span<byte, Dimensions...>::bounds_type::static_size != dynamic_range multi_span<byte, Dimensions...>::bounds_type::static_size != dynamic_range
? static_cast<std::size_t>(multi_span<byte, Dimensions...>::bounds_type::static_size) / ? static_cast<std::size_t>(
sizeof(U) multi_span<byte, Dimensions...>::bounds_type::static_size) /
: dynamic_range)> sizeof(U)
: dynamic_range)>
{ {
using ByteSpan = multi_span<byte, Dimensions...>; using ByteSpan = multi_span<byte, Dimensions...>;
static_assert( static_assert(
@ -1816,9 +1822,9 @@ public:
auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type)); auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type));
size_type size = this->bounds().total_size() / d; size_type size = this->bounds().total_size() / d;
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())), size, return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
bounds_type{resize_extent(this->bounds().index_bounds(), d), size, bounds_type{resize_extent(this->bounds().index_bounds(), d),
resize_stride(this->bounds().strides(), d)}}; resize_stride(this->bounds().strides(), d)}};
} }
constexpr strided_span section(index_type origin, index_type extents) const constexpr strided_span section(index_type origin, index_type extents) const
@ -2049,7 +2055,7 @@ public:
contiguous_span_iterator ret{*this}; contiguous_span_iterator ret{*this};
return ret -= n; 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 difference_type operator-(const contiguous_span_iterator& rhs) const noexcept
{ {
Expects(m_validator == rhs.m_validator); Expects(m_validator == rhs.m_validator);
@ -2148,16 +2154,13 @@ public:
general_span_iterator ret{*this}; general_span_iterator ret{*this};
return ret -= n; 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 difference_type operator-(const general_span_iterator& rhs) const noexcept
{ {
Expects(m_container == rhs.m_container); Expects(m_container == rhs.m_container);
return m_itr - rhs.m_itr; return m_itr - rhs.m_itr;
} }
value_type operator[](difference_type n) const noexcept value_type operator[](difference_type n) const noexcept { return (*m_container)[m_itr[n]]; }
{
return (*m_container)[m_itr[n]];
}
bool operator==(const general_span_iterator& rhs) const noexcept bool operator==(const general_span_iterator& rhs) const noexcept
{ {

File diff suppressed because it is too large Load Diff

@ -36,8 +36,7 @@
// blanket turn off warnings from CppCoreCheck for now // blanket turn off warnings from CppCoreCheck for now
// so people aren't annoyed by them when running the tool. // so people aren't annoyed by them when running the tool.
// more targeted suppressions will be added in a future update to the GSL // 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 // VS 2013 workarounds
#if _MSC_VER <= 1800 #if _MSC_VER <= 1800
@ -80,19 +79,19 @@ namespace gsl
// (sometimes needlessly) break existing programs when introduced. // (sometimes needlessly) break existing programs when introduced.
// //
template<typename CharT, std::ptrdiff_t Extent = dynamic_extent> template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
using basic_zstring = CharT*; using basic_zstring = CharT*;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using czstring = basic_zstring<const char, Extent>; using czstring = basic_zstring<const char, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using cwzstring = basic_zstring<const wchar_t, Extent>; using cwzstring = basic_zstring<const wchar_t, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using zstring = basic_zstring<char, Extent>; using zstring = basic_zstring<char, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using wzstring = basic_zstring<wchar_t, Extent>; using wzstring = basic_zstring<wchar_t, Extent>;
// //
@ -103,85 +102,93 @@ using wzstring = basic_zstring<wchar_t, Extent>;
// //
// Will fail-fast if sentinel cannot be found before max elements are examined. // Will fail-fast if sentinel cannot be found before max elements are examined.
// //
template<typename T, const T Sentinel> template <typename T, const T Sentinel>
span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX) span<T, dynamic_extent> ensure_sentinel(T* seq, std::ptrdiff_t max = PTRDIFF_MAX)
{ {
auto cur = seq; auto cur = seq;
while ((cur - seq) < max && *cur != Sentinel) ++cur; while ((cur - seq) < max && *cur != Sentinel) ++cur;
Ensures(*cur == Sentinel); Ensures(*cur == Sentinel);
return{ seq, cur - seq }; return {seq, cur - seq};
} }
// //
// ensure_z - creates a span for a czstring or cwzstring. // ensure_z - creates a span for a czstring or cwzstring.
// Will fail fast if a null-terminator cannot be found before // Will fail fast if a null-terminator cannot be found before
// the limit of size_type. // the limit of size_type.
// //
template<typename T> template <typename T>
inline span<T, dynamic_extent> ensure_z(T* const & sz, std::ptrdiff_t max = PTRDIFF_MAX) inline span<T, dynamic_extent> ensure_z(T* const& sz, std::ptrdiff_t max = PTRDIFF_MAX)
{ {
return ensure_sentinel<T, 0>(sz, max); return ensure_sentinel<T, 0>(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<char, dynamic_extent> ensure_z(char* const& sz, std::ptrdiff_t max) inline span<char, dynamic_extent> ensure_z(char* const& sz, std::ptrdiff_t max)
{ {
auto len = strnlen(sz, narrow_cast<size_t>(max)); auto len = strnlen(sz, narrow_cast<size_t>(max));
Ensures(sz[len] == 0); Ensures(sz[len] == 0);
return{ sz, static_cast<std::ptrdiff_t>(len) }; return {sz, static_cast<std::ptrdiff_t>(len)};
} }
inline span<const char, dynamic_extent> ensure_z(const char* const& sz, std::ptrdiff_t max) inline span<const char, dynamic_extent> ensure_z(const char* const& sz, std::ptrdiff_t max)
{ {
auto len = strnlen(sz, narrow_cast<size_t>(max)); auto len = strnlen(sz, narrow_cast<size_t>(max));
Ensures(sz[len] == 0); Ensures(sz[len] == 0);
return{ sz, static_cast<std::ptrdiff_t>(len) }; return {sz, static_cast<std::ptrdiff_t>(len)};
} }
inline span<wchar_t, dynamic_extent> ensure_z(wchar_t* const& sz, std::ptrdiff_t max) inline span<wchar_t, dynamic_extent> ensure_z(wchar_t* const& sz, std::ptrdiff_t max)
{ {
auto len = wcsnlen(sz, narrow_cast<size_t>(max)); auto len = wcsnlen(sz, narrow_cast<size_t>(max));
Ensures(sz[len] == 0); Ensures(sz[len] == 0);
return{ sz, static_cast<std::ptrdiff_t>(len) }; return {sz, static_cast<std::ptrdiff_t>(len)};
} }
inline span<const wchar_t, dynamic_extent> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max) inline span<const wchar_t, dynamic_extent> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max)
{ {
auto len = wcsnlen(sz, narrow_cast<size_t>(max)); auto len = wcsnlen(sz, narrow_cast<size_t>(max));
Ensures(sz[len] == 0); Ensures(sz[len] == 0);
return{ sz, static_cast<std::ptrdiff_t>(len) }; return {sz, static_cast<std::ptrdiff_t>(len)};
} }
template<typename T, size_t N> template <typename T, size_t N>
span<T, dynamic_extent> ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], static_cast<std::ptrdiff_t>(N)); } span<T, dynamic_extent> ensure_z(T (&sz)[N])
{
return ensure_z(&sz[0], static_cast<std::ptrdiff_t>(N));
}
template<class Cont> template <class Cont>
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent> ensure_z(Cont& cont) span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent>
ensure_z(Cont& cont)
{ {
return ensure_z(cont.data(), static_cast<std::ptrdiff_t>(cont.length())); return ensure_z(cont.data(), static_cast<std::ptrdiff_t>(cont.length()));
} }
template<typename CharT, std::ptrdiff_t> template <typename CharT, std::ptrdiff_t>
class basic_string_span; class basic_string_span;
namespace details namespace details
{ {
template <typename T> template <typename T>
struct is_basic_string_span_oracle : std::false_type struct is_basic_string_span_oracle : std::false_type
{}; {
};
template <typename CharT, std::ptrdiff_t Extent> template <typename CharT, std::ptrdiff_t Extent>
struct is_basic_string_span_oracle<basic_string_span<CharT, Extent>> : std::true_type struct is_basic_string_span_oracle<basic_string_span<CharT, Extent>> : std::true_type
{}; {
};
template <typename T> template <typename T>
struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>> struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
{}; {
};
template <typename T> template <typename T>
struct length_func struct length_func
{}; {
};
template <> template <>
struct length_func<char> struct length_func<char>
@ -220,7 +227,6 @@ namespace details
}; };
} }
// //
// string_span and relatives // string_span and relatives
// //
@ -247,19 +253,17 @@ public:
// copy // copy
constexpr basic_string_span(const basic_string_span& other) = default; constexpr basic_string_span(const basic_string_span& other) = default;
// move // move
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
constexpr basic_string_span(basic_string_span&& other) = default; constexpr basic_string_span(basic_string_span&& other) = default;
#else #else
constexpr basic_string_span(basic_string_span&& other) constexpr basic_string_span(basic_string_span&& other) : span_(std::move(other.span_)) {}
: span_(std::move(other.span_))
{}
#endif #endif
// assign // assign
constexpr basic_string_span& operator=(const basic_string_span& other) = default; constexpr basic_string_span& operator=(const basic_string_span& other) = default;
// move assign // move assign
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
constexpr basic_string_span& operator=(basic_string_span&& other) = default; constexpr basic_string_span& operator=(basic_string_span&& other) = default;
#else #else
@ -271,211 +275,160 @@ public:
#endif #endif
// from nullptr // from nullptr
constexpr basic_string_span(std::nullptr_t ptr) noexcept constexpr basic_string_span(std::nullptr_t ptr) noexcept : span_(ptr) {}
: span_(ptr)
{}
// from nullptr and length // from nullptr and length
constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept : span_(ptr, length)
: span_(ptr, length) {
{} }
// From static arrays - if 0-terminated, remove 0 from the view // From static arrays - if 0-terminated, remove 0 from the view
// from static arrays and string literals // from static arrays and string literals
template<size_t N> template <size_t N>
constexpr basic_string_span(value_type(&arr)[N]) noexcept constexpr basic_string_span(value_type (&arr)[N]) noexcept : span_(remove_z(arr))
: span_(remove_z(arr)) {
{} }
// Those allow 0s within the length, so we do not remove them // Those allow 0s within the length, so we do not remove them
// from raw data and length // from raw data and length
constexpr basic_string_span(pointer ptr, size_type length) noexcept constexpr basic_string_span(pointer ptr, size_type length) noexcept : span_(ptr, length) {}
: span_(ptr, length)
{}
// from string // from string
constexpr basic_string_span(std::string& s) noexcept constexpr basic_string_span(std::string& s) noexcept
: span_(const_cast<pointer>(s.data()), narrow_cast<std::ptrdiff_t>(s.length())) : span_(const_cast<pointer>(s.data()), narrow_cast<std::ptrdiff_t>(s.length()))
{} {
}
// from containers. Containers must have .size() and .data() function signatures // from containers. Containers must have .size() and .data() function signatures
template <typename Cont, template <typename Cont,
typename = std::enable_if_t< typename = std::enable_if_t<
!details::is_basic_string_span<Cont>::value !details::is_basic_string_span<Cont>::value && !details::is_span<Cont>::value &&
&& !details::is_span<Cont>::value std::is_convertible<Cont::pointer, pointer>::value &&
&& std::is_convertible<Cont::pointer, pointer>::value std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>>
&& std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value> constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size())
> {
constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size()) {} }
// disallow creation from temporary containers and strings // disallow creation from temporary containers and strings
template <typename Cont, template <typename Cont,
typename = std::enable_if_t< typename = std::enable_if_t<
!details::is_basic_string_span<Cont>::value !details::is_basic_string_span<Cont>::value && !details::is_span<Cont>::value &&
&& !details::is_span<Cont>::value std::is_convertible<Cont::pointer, pointer>::value &&
&& std::is_convertible<Cont::pointer, pointer>::value std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>>
&& std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value> constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size())
> {
constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size()) {} }
#ifndef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE #ifndef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE
// from span // from span
template <typename OtherValueType, std::ptrdiff_t OtherExtent, template <typename OtherValueType, std::ptrdiff_t OtherExtent,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<span<OtherValueType, OtherExtent>, impl_type>::value std::is_convertible<span<OtherValueType, OtherExtent>, impl_type>::value>>
> constexpr basic_string_span(span<OtherValueType, OtherExtent> other) noexcept : span_(other)
> {
constexpr basic_string_span(span<OtherValueType, OtherExtent> other) noexcept }
: span_(other)
{}
#else #else
// from span // from span
constexpr basic_string_span(span<value_type, Extent> other) noexcept constexpr basic_string_span(span<value_type, Extent> other) noexcept : span_(other) {}
: span_(other)
{} template <typename = std::enable_if_t<
!std::is_same<std::remove_const_t<value_type>, value_type>::value>>
template <typename = std::enable_if_t<!std::is_same<std::remove_const_t<value_type>, value_type>::value>>
constexpr basic_string_span(span<std::remove_const_t<value_type>, Extent> other) noexcept constexpr basic_string_span(span<std::remove_const_t<value_type>, Extent> other) noexcept
: span_(other) : span_(other)
{} {
}
#endif #endif
// from string_span // from string_span
template <typename OtherValueType, std::ptrdiff_t OtherExtent, template <typename OtherValueType, std::ptrdiff_t OtherExtent,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
>
>
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept
: span_(other.data(), other.length()) : span_(other.data(), other.length())
{}
constexpr bool empty() const noexcept
{ {
return length() == 0;
} }
constexpr bool empty() const noexcept { return length() == 0; }
// first Count elements // first Count elements
template<size_type Count> template <size_type Count>
constexpr basic_string_span<value_type, Count> first() const noexcept constexpr basic_string_span<value_type, Count> first() const noexcept
{ {
return{ span_.template first<Count>() }; return {span_.template first<Count>()};
} }
constexpr basic_string_span<value_type, dynamic_extent> first(size_type count) const noexcept constexpr basic_string_span<value_type, dynamic_extent> first(size_type count) const noexcept
{ {
return{ span_.first(count) }; return {span_.first(count)};
} }
// last Count elements // last Count elements
template<size_type Count> template <size_type Count>
constexpr basic_string_span<value_type, Count> last() const noexcept constexpr basic_string_span<value_type, Count> last() const noexcept
{ {
return{ span_.template last<Count>() }; return {span_.template last<Count>()};
} }
constexpr basic_string_span<value_type, dynamic_extent> last(size_type count) const noexcept constexpr basic_string_span<value_type, dynamic_extent> last(size_type count) const noexcept
{ {
return{ span_.last(count) }; return {span_.last(count)};
} }
// create a subview of Count elements starting from Offset // create a subview of Count elements starting from Offset
template<size_type Offset, size_type Count> template <size_type Offset, size_type Count>
constexpr basic_string_span<value_type, Count> subspan() const noexcept constexpr basic_string_span<value_type, Count> subspan() const noexcept
{ {
return{ span_.template subspan<Offset, Count>() }; return {span_.template subspan<Offset, Count>()};
} }
constexpr basic_string_span<value_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const noexcept constexpr basic_string_span<value_type, dynamic_extent>
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 constexpr reference operator[](size_type idx) const noexcept { return span_[idx]; }
{
return span_[idx];
}
constexpr pointer data() const noexcept constexpr pointer data() const noexcept { return span_.data(); }
{
return span_.data();
}
// length of the span in elements // length of the span in elements
constexpr size_type length() const noexcept constexpr size_type length() const noexcept { return span_.size(); }
{
return span_.size();
}
// length of the span in elements // length of the span in elements
constexpr size_type size() const noexcept constexpr size_type size() const noexcept { return span_.size(); }
{
return span_.size();
}
// length of the span in bytes // length of the span in bytes
constexpr size_type size_bytes() const noexcept constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); }
{
return span_.size_bytes();
}
// length of the span in bytes // length of the span in bytes
constexpr size_type length_bytes() const noexcept constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); }
{
return span_.length_bytes();
}
constexpr iterator begin() const noexcept constexpr iterator begin() const noexcept { return span_.begin(); }
{
return span_.begin();
}
constexpr iterator end() const noexcept constexpr iterator end() const noexcept { return span_.end(); }
{
return span_.end();
}
constexpr const_iterator cbegin() const noexcept constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); }
{
return span_.cbegin();
}
constexpr const_iterator cend() const noexcept constexpr const_iterator cend() const noexcept { return span_.cend(); }
{
return span_.cend();
}
constexpr reverse_iterator rbegin() const noexcept constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
{
return span_.rbegin();
}
constexpr reverse_iterator rend() const noexcept constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
{
return span_.rend();
}
constexpr const_reverse_iterator crbegin() const noexcept constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); }
{
return span_.crbegin();
}
constexpr const_reverse_iterator crend() const noexcept constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); }
{
return span_.crend();
}
private: private:
static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) noexcept static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) noexcept
{ {
return{ sz, details::length_func<value_type>()(sz, max)}; return {sz, details::length_func<value_type>()(sz, max)};
} }
template<size_t N> template <size_t N>
static impl_type remove_z(value_type(&sz)[N]) noexcept static impl_type remove_z(value_type (&sz)[N]) noexcept
{ {
return remove_z(&sz[0], narrow_cast<std::ptrdiff_t>(N)); return remove_z(&sz[0], narrow_cast<std::ptrdiff_t>(N));
} }
@ -483,16 +436,16 @@ private:
impl_type span_; impl_type span_;
}; };
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using string_span = basic_string_span<char, Extent>; using string_span = basic_string_span<char, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using cstring_span = basic_string_span<const char, Extent>; using cstring_span = basic_string_span<const char, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using wstring_span = basic_string_span<wchar_t, Extent>; using wstring_span = basic_string_span<wchar_t, Extent>;
template<std::ptrdiff_t Extent = dynamic_extent> template <std::ptrdiff_t Extent = dynamic_extent>
using cwstring_span = basic_string_span<const wchar_t, Extent>; using cwstring_span = basic_string_span<const wchar_t, Extent>;
// //
@ -500,39 +453,40 @@ using cwstring_span = basic_string_span<const wchar_t, Extent>;
// //
#ifndef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG #ifndef GSL_MSVC_HAS_TYPE_DEDUCTION_BUG
template<typename CharT, ptrdiff_t Extent> template <typename CharT, ptrdiff_t Extent>
std::basic_string<typename std::remove_const<CharT>::type> to_string(basic_string_span<CharT, Extent> view) std::basic_string<typename std::remove_const<CharT>::type>
to_string(basic_string_span<CharT, Extent> view)
{ {
return{ view.data(), static_cast<size_t>(view.length()) }; return {view.data(), static_cast<size_t>(view.length())};
} }
#else #else
inline std::string to_string(cstring_span<> view) inline std::string to_string(cstring_span<> view)
{ {
return{ view.data(), static_cast<size_t>(view.length()) }; return {view.data(), static_cast<size_t>(view.length())};
} }
inline std::string to_string(string_span<> view) inline std::string to_string(string_span<> view)
{ {
return{ view.data(), static_cast<size_t>(view.length()) }; return {view.data(), static_cast<size_t>(view.length())};
} }
inline std::wstring to_string(cwstring_span<> view) inline std::wstring to_string(cwstring_span<> view)
{ {
return{ view.data(), static_cast<size_t>(view.length()) }; return {view.data(), static_cast<size_t>(view.length())};
} }
inline std::wstring to_string(wstring_span<> view) inline std::wstring to_string(wstring_span<> view)
{ {
return{ view.data(), static_cast<size_t>(view.length()) }; return {view.data(), static_cast<size_t>(view.length())};
} }
#endif #endif
// zero-terminated string span, used to convert // zero-terminated string span, used to convert
// zero-terminated spans to legacy strings // zero-terminated spans to legacy strings
template<typename CharT, std::ptrdiff_t Extent = dynamic_extent> template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
class basic_zstring_span class basic_zstring_span
{ {
public: public:
@ -548,8 +502,7 @@ public:
using impl_type = span<value_type, Extent>; using impl_type = span<value_type, Extent>;
using string_span_type = basic_string_span<value_type, Extent>; using string_span_type = basic_string_span<value_type, Extent>;
constexpr basic_zstring_span(impl_type s) noexcept constexpr basic_zstring_span(impl_type s) noexcept : span_(s)
: span_(s)
{ {
// expects a zero-terminated span // expects a zero-terminated span
Expects(s[s.size() - 1] == '\0'); Expects(s[s.size() - 1] == '\0');
@ -558,19 +511,17 @@ public:
// copy // copy
constexpr basic_zstring_span(const basic_zstring_span& other) = default; constexpr basic_zstring_span(const basic_zstring_span& other) = default;
// move // move
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
constexpr basic_zstring_span(basic_zstring_span&& other) = default; constexpr basic_zstring_span(basic_zstring_span&& other) = default;
#else #else
constexpr basic_zstring_span(basic_zstring_span&& other) constexpr basic_zstring_span(basic_zstring_span&& other) : span_(std::move(other.span_)) {}
: span_(std::move(other.span_))
{}
#endif #endif
// assign // assign
constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default; constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;
// move assign // move assign
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR #ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default; constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
#else #else
@ -583,7 +534,10 @@ public:
constexpr bool empty() const noexcept { return span_.size() == 0; } 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_); } constexpr string_span_type ensure_z() const noexcept { return gsl::ensure_z(span_); }
@ -609,9 +563,8 @@ using cwzstring_span = basic_zstring_span<const wchar_t, Max>;
// operator == // operator ==
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
@ -622,11 +575,11 @@ bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexc
#endif #endif
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
@ -637,33 +590,33 @@ bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
#endif #endif
} }
#ifndef _MSC_VER #ifndef _MSC_VER
// VS treats temp and const containers as convertible to basic_string_span, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator==(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end()); return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end());
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
@ -673,50 +626,49 @@ bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
// operator != // operator !=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(one == other); return !(one == other);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(one == other); return !(one == other);
} }
#ifndef _MSC_VER #ifndef _MSC_VER
// VS treats temp and const containers as convertible to basic_string_span, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(one == other); return !(one == other);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(one == other); return !(one == other);
@ -725,53 +677,52 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
// operator< // operator<
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end()); 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, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end()); return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one); gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
@ -781,50 +732,49 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
// operator <= // operator <=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(other < one); return !(other < one);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(other < one); return !(other < one);
} }
#ifndef _MSC_VER #ifndef _MSC_VER
// VS treats temp and const containers as convertible to basic_string_span, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(other < one); return !(other < one);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(other < one); return !(other < one);
@ -833,50 +783,49 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
// operator> // operator>
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return other < one; return other < one;
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return other < one; return other < one;
} }
#ifndef _MSC_VER #ifndef _MSC_VER
// VS treats temp and const containers as convertible to basic_string_span, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return other < one; return other < one;
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return other < one; return other < one;
@ -885,50 +834,49 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
// operator >= // operator >=
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename = std::enable_if_t< typename = std::enable_if_t<std::is_convertible<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value> T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(one < other); return !(one < other);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
&& !gsl::details::is_basic_string_span<T>::value> !gsl::details::is_basic_string_span<T>::value>>
>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(one < other); return !(one < other);
} }
#ifndef _MSC_VER #ifndef _MSC_VER
// VS treats temp and const containers as convertible to basic_string_span, // VS treats temp and const containers as convertible to basic_string_span,
// so the cases below are already covered by the previous operators // so the cases below are already covered by the previous operators
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
{ {
return !(one < other); return !(one < other);
} }
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T, template <
typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
typename DataType = typename T::value_type, typename DataType = typename T::value_type,
typename Dummy = std::enable_if_t< typename Dummy = std::enable_if_t<
!gsl::details::is_span<T>::value !gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
&& !gsl::details::is_basic_string_span<T>::value std::is_convertible<DataType*, CharT*>::value &&
&& std::is_convertible<DataType*, CharT*>::value std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value> DataType>::value>>
>
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
{ {
return !(one < other); return !(one < other);