mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-25 01:01:58 -05:00
Applied clang-format to the source.
This commit is contained in:
parent
ca4cdd80de
commit
b03b04bfcd
@ -16,6 +16,6 @@ AllowShortLoopsOnASingleLine: true
|
||||
|
||||
PointerAlignment: Left
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignTrailingComments: false
|
||||
AlignTrailingComments: true
|
||||
|
||||
SpaceAfterCStyleCast: true
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
#include "gsl_assert.h" // Ensures/Expects
|
||||
#include "gsl_util.h" // finally()/narrow()/narrow_cast()...
|
||||
#include "span.h" // span
|
||||
#include "multi_span.h" // multi_span, strided_span...
|
||||
#include "span.h" // span
|
||||
#include "string_span.h" // zstring, string_span, zstring_builder...
|
||||
#include <memory>
|
||||
|
||||
@ -40,13 +40,12 @@
|
||||
|
||||
// turn off some misguided warnings
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior
|
||||
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
|
||||
|
||||
#endif // _MSC_VER <= 1800
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
@ -59,7 +58,6 @@ using std::shared_ptr;
|
||||
template <class T>
|
||||
using owner = T;
|
||||
|
||||
|
||||
//
|
||||
// not_null
|
||||
//
|
||||
@ -74,25 +72,31 @@ using owner = T;
|
||||
// - ensure construction from U* fails with nullptr
|
||||
// - allow implicit conversion to U*
|
||||
//
|
||||
template<class T>
|
||||
template <class T>
|
||||
class not_null
|
||||
{
|
||||
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
|
||||
|
||||
public:
|
||||
not_null(T t) : ptr_(t) { ensure_invariant(); }
|
||||
not_null& operator=(const T& t) { ptr_ = t; ensure_invariant(); return *this; }
|
||||
not_null& operator=(const T& t)
|
||||
{
|
||||
ptr_ = t;
|
||||
ensure_invariant();
|
||||
return *this;
|
||||
}
|
||||
|
||||
not_null(const not_null &other) = default;
|
||||
not_null& operator=(const not_null &other) = default;
|
||||
not_null(const not_null& other) = default;
|
||||
not_null& operator=(const not_null& other) = default;
|
||||
|
||||
template <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;
|
||||
}
|
||||
|
||||
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();
|
||||
return *this;
|
||||
@ -104,7 +108,8 @@ public:
|
||||
not_null<T>& operator=(std::nullptr_t) = delete;
|
||||
not_null<T>& operator=(int) = delete;
|
||||
|
||||
T get() const {
|
||||
T get() const
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__assume(ptr_ != nullptr);
|
||||
#endif
|
||||
@ -119,7 +124,8 @@ public:
|
||||
private:
|
||||
T ptr_;
|
||||
|
||||
// we assume that the compiler can hoist/prove away most of the checks inlined from this function
|
||||
// we assume that the compiler can hoist/prove away most of the checks inlined from this
|
||||
// function
|
||||
// if not, we could make them optional via conditional compilation
|
||||
void ensure_invariant() const { Expects(ptr_ != nullptr); }
|
||||
|
||||
@ -139,14 +145,11 @@ private:
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class T>
|
||||
struct hash<gsl::not_null<T>>
|
||||
{
|
||||
size_t operator()(const gsl::not_null<T> & value) const
|
||||
{
|
||||
return hash<T>{}(value);
|
||||
}
|
||||
};
|
||||
template <class T>
|
||||
struct hash<gsl::not_null<T>>
|
||||
{
|
||||
size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
@ -30,15 +30,14 @@
|
||||
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
|
||||
// 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) ^ \
|
||||
defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
|
||||
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
|
||||
#endif
|
||||
|
||||
|
||||
#define GSL_STRINGIFY_DETAIL(x) #x
|
||||
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
|
||||
|
||||
|
||||
//
|
||||
// GSL.assert: assertions
|
||||
//
|
||||
@ -53,18 +52,20 @@ struct fail_fast : public std::runtime_error
|
||||
|
||||
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
|
||||
|
||||
#define Expects(cond) if (!(cond)) \
|
||||
#define Expects(cond) \
|
||||
if (!(cond)) \
|
||||
throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
|
||||
#define Ensures(cond) if (!(cond)) \
|
||||
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
|
||||
|
||||
#define Ensures(cond) \
|
||||
if (!(cond)) \
|
||||
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ \
|
||||
": " GSL_STRINGIFY(__LINE__));
|
||||
|
||||
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
|
||||
|
||||
|
||||
#define Expects(cond) if (!(cond)) std::terminate();
|
||||
#define Ensures(cond) if (!(cond)) std::terminate();
|
||||
|
||||
#define Expects(cond) \
|
||||
if (!(cond)) std::terminate();
|
||||
#define Ensures(cond) \
|
||||
if (!(cond)) std::terminate();
|
||||
|
||||
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
|
||||
|
||||
@ -73,5 +74,4 @@ struct fail_fast : public std::runtime_error
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // GSL_CONTRACTS_H
|
||||
|
@ -38,54 +38,76 @@
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
// This is a simple definition for now that allows
|
||||
// use of byte within span<> to be standards-compliant
|
||||
enum class byte : unsigned char {};
|
||||
// This is a simple definition for now that allows
|
||||
// use of byte within span<> to be standards-compliant
|
||||
enum class byte : unsigned char
|
||||
{
|
||||
};
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
|
||||
{ return b = byte(static_cast<unsigned char>(b) << shift); }
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
|
||||
{
|
||||
return b = byte(static_cast<unsigned char>(b) << shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator<<(byte b, IntegerType shift) noexcept
|
||||
{ return byte(static_cast<unsigned char>(b) << shift); }
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator<<(byte b, IntegerType shift) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(b) << shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
|
||||
{ return b = byte(static_cast<unsigned char>(b) >> shift); }
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
|
||||
{
|
||||
return b = byte(static_cast<unsigned char>(b) >> shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator>> (byte b, IntegerType shift) noexcept
|
||||
{ return byte(static_cast<unsigned char>(b) >> shift); }
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator>>(byte b, IntegerType shift) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(b) >> shift);
|
||||
}
|
||||
|
||||
constexpr byte& operator|=(byte& l, byte r) noexcept
|
||||
{ return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r)); }
|
||||
constexpr byte& operator|=(byte& l, byte r) noexcept
|
||||
{
|
||||
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 l, byte r) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(l) + static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte& operator&=(byte& l, byte r) noexcept
|
||||
{ return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r)); }
|
||||
constexpr byte& operator&=(byte& l, byte r) noexcept
|
||||
{
|
||||
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 l, byte r) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte& operator^=(byte& l, byte r) noexcept
|
||||
{ return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r)); }
|
||||
constexpr byte& operator^=(byte& l, byte r) noexcept
|
||||
{
|
||||
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 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 IntegerType to_integer(byte b) noexcept { return {b}; }
|
||||
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
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER <= 1800
|
||||
|
@ -21,9 +21,9 @@
|
||||
|
||||
#include "gsl_assert.h" // Ensures/Expects
|
||||
#include <array>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
#define constexpr
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
|
||||
// MSVC 2013 workarounds
|
||||
#if _MSC_VER <= 1800
|
||||
@ -42,13 +42,12 @@
|
||||
|
||||
// turn off some misguided warnings
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4351) // warns about newly introduced aggregate initializer behavior
|
||||
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
|
||||
|
||||
#endif // _MSC_VER <= 1800
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
//
|
||||
@ -60,18 +59,20 @@ template <class F>
|
||||
class final_act
|
||||
{
|
||||
public:
|
||||
explicit final_act(F f) noexcept
|
||||
: f_(std::move(f)), invoke_(true)
|
||||
{}
|
||||
explicit final_act(F f) noexcept : f_(std::move(f)), invoke_(true) {}
|
||||
|
||||
final_act(final_act&& other) noexcept
|
||||
: f_(std::move(other.f_)), invoke_(other.invoke_)
|
||||
{ other.invoke_ = false; }
|
||||
final_act(final_act&& other) noexcept : f_(std::move(other.f_)), invoke_(other.invoke_)
|
||||
{
|
||||
other.invoke_ = false;
|
||||
}
|
||||
|
||||
final_act(const final_act&) = delete;
|
||||
final_act& operator=(const final_act&) = delete;
|
||||
|
||||
~final_act() noexcept { if (invoke_) f_(); }
|
||||
~final_act() noexcept
|
||||
{
|
||||
if (invoke_) f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
@ -80,35 +81,44 @@ private:
|
||||
|
||||
// finally() - convenience function to generate a final_act
|
||||
template <class F>
|
||||
inline final_act<F> finally(const F &f)
|
||||
noexcept { return final_act<F>(f); }
|
||||
inline final_act<F> finally(const F& f) noexcept
|
||||
{
|
||||
return final_act<F>(f);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
inline final_act<F> finally(F &&f) noexcept
|
||||
{ return final_act<F>(std::forward<F>(f)); }
|
||||
inline final_act<F> finally(F&& f) noexcept
|
||||
{
|
||||
return final_act<F>(std::forward<F>(f));
|
||||
}
|
||||
|
||||
// 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
|
||||
{ return static_cast<T>(u); }
|
||||
{
|
||||
return static_cast<T>(u);
|
||||
}
|
||||
|
||||
struct narrowing_error : public std::exception {};
|
||||
struct narrowing_error : public std::exception
|
||||
{
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<class T, class U>
|
||||
struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
|
||||
{};
|
||||
template <class T, class U>
|
||||
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
|
||||
template<class T, class U>
|
||||
template <class T, class U>
|
||||
inline T narrow(U u)
|
||||
{
|
||||
T t = narrow_cast<T>(u);
|
||||
if (static_cast<U>(t) != u)
|
||||
throw narrowing_error();
|
||||
#pragma warning(suppress:4127) // suppress warning from MSVC compiler about constant in if-test
|
||||
if (static_cast<U>(t) != u) throw narrowing_error();
|
||||
#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{})))
|
||||
throw narrowing_error();
|
||||
return t;
|
||||
@ -118,24 +128,35 @@ inline T narrow(U u)
|
||||
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector
|
||||
//
|
||||
template <class T, size_t N>
|
||||
constexpr T& at(T(&arr)[N], size_t index)
|
||||
{ Expects(index < N); return arr[index]; }
|
||||
constexpr T& at(T (&arr)[N], size_t index)
|
||||
{
|
||||
Expects(index < N);
|
||||
return arr[index];
|
||||
}
|
||||
|
||||
template <class T, size_t N>
|
||||
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>
|
||||
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>
|
||||
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
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning(pop)
|
||||
|
@ -20,8 +20,8 @@
|
||||
#define GSL_MULTI_SPAN_H
|
||||
|
||||
#include "gsl_assert.h"
|
||||
#include "gsl_util.h"
|
||||
#include "gsl_byte.h"
|
||||
#include "gsl_util.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
@ -217,10 +217,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend constexpr index operator*(value_type v, const index& rhs) noexcept
|
||||
{
|
||||
return rhs * v;
|
||||
}
|
||||
friend constexpr index operator*(value_type v, const index& rhs) noexcept { return rhs * v; }
|
||||
|
||||
constexpr index& operator*=(value_type v) noexcept
|
||||
{
|
||||
@ -743,8 +740,7 @@ public:
|
||||
}
|
||||
|
||||
constexpr strided_bounds(const index_type& extents, const index_type& strides) noexcept
|
||||
: m_extents(extents),
|
||||
m_strides(strides)
|
||||
: m_extents(extents), m_strides(strides)
|
||||
{
|
||||
}
|
||||
|
||||
@ -841,8 +837,7 @@ public:
|
||||
using index_size_type = typename IndexType::value_type;
|
||||
template <typename Bounds>
|
||||
explicit bounds_iterator(const Bounds& bnd, value_type curr) noexcept
|
||||
: boundary_(bnd.index_bounds()),
|
||||
curr_(std::move(curr))
|
||||
: boundary_(bnd.index_bounds()), curr_(std::move(curr))
|
||||
{
|
||||
static_assert(is_bounds<Bounds>::value, "Bounds type must be provided");
|
||||
}
|
||||
@ -930,7 +925,7 @@ public:
|
||||
return ret -= n;
|
||||
}
|
||||
|
||||
constexpr bounds_iterator& operator-=(difference_type n) noexcept { return * this += -n; }
|
||||
constexpr bounds_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
|
||||
|
||||
constexpr difference_type operator-(const bounds_iterator& rhs) const noexcept
|
||||
{
|
||||
@ -1159,7 +1154,8 @@ namespace details
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
// construct from pointer + length
|
||||
constexpr multi_span(pointer ptr, size_type size) noexcept : multi_span(ptr, bounds_type{size}) {}
|
||||
constexpr multi_span(pointer ptr, size_type size) noexcept : multi_span(ptr, bounds_type{size})
|
||||
{
|
||||
}
|
||||
|
||||
// construct from pointer + length - multidimensional
|
||||
constexpr multi_span(pointer data, bounds_type bounds) noexcept : data_(data),
|
||||
bounds_(std::move(bounds))
|
||||
constexpr multi_span(pointer data, bounds_type bounds) noexcept
|
||||
: data_(data), bounds_(std::move(bounds))
|
||||
{
|
||||
Expects((bounds_.size() > 0 && data != nullptr) || bounds_.size() == 0);
|
||||
}
|
||||
@ -1263,7 +1261,8 @@ public:
|
||||
typename = std::enable_if_t<std::is_convertible<Ptr, pointer>::value &&
|
||||
details::LessThan<bounds_type::dynamic_rank, 2>::value>>
|
||||
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));
|
||||
}
|
||||
@ -1273,8 +1272,7 @@ public:
|
||||
constexpr multi_span(T (&arr)[N])
|
||||
: multi_span(reinterpret_cast<pointer>(arr), bounds_type{typename Helper::bounds_type{}})
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible<typename Helper::value_type(*) [], value_type(*) []>::value,
|
||||
static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
|
||||
"Cannot convert from source type to target multi_span type.");
|
||||
static_assert(std::is_convertible<typename Helper::bounds_type, bounds_type>::value,
|
||||
"Cannot construct a multi_span from an array with fewer elements.");
|
||||
@ -1286,17 +1284,17 @@ public:
|
||||
constexpr multi_span(T* const& data, size_type size)
|
||||
: multi_span(reinterpret_cast<pointer>(data), typename Helper::bounds_type{size})
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible<typename Helper::value_type(*) [], value_type(*) []>::value,
|
||||
static_assert(std::is_convertible<typename Helper::value_type(*)[], value_type(*)[]>::value,
|
||||
"Cannot convert from source type to target multi_span type.");
|
||||
}
|
||||
|
||||
// construct from std::array
|
||||
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(
|
||||
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.");
|
||||
static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
|
||||
"You cannot construct a multi_span from a std::array of smaller size.");
|
||||
@ -1307,7 +1305,7 @@ public:
|
||||
constexpr multi_span(const std::array<std::remove_const_t<value_type>, N>& arr)
|
||||
: 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.");
|
||||
static_assert(std::is_convertible<static_bounds<N>, bounds_type>::value,
|
||||
"You cannot construct a multi_span from a std::array of smaller size.");
|
||||
@ -1348,8 +1346,8 @@ public:
|
||||
typename OtherBounds = static_bounds<OtherDimensions...>,
|
||||
typename = std::enable_if_t<std::is_convertible<OtherValueType, ValueType>::value &&
|
||||
std::is_convertible<OtherBounds, bounds_type>::value>>
|
||||
constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) noexcept : data_(other.data_),
|
||||
bounds_(other.bounds_)
|
||||
constexpr multi_span(multi_span<OtherValueType, OtherDimensions...> other) noexcept
|
||||
: data_(other.data_), bounds_(other.bounds_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1424,7 +1422,8 @@ public:
|
||||
// subspan() - create a subview of count elements starting at offset
|
||||
// supplying dynamic_range for count will consume all available elements from offset
|
||||
constexpr multi_span<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()) &&
|
||||
(count == dynamic_range || (count <= this->size() - offset)));
|
||||
@ -1535,7 +1534,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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() &&
|
||||
(data_ == other.data_ || std::equal(this->begin(), this->end(), other.begin()));
|
||||
@ -1544,7 +1544,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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);
|
||||
}
|
||||
@ -1552,7 +1553,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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());
|
||||
}
|
||||
@ -1560,7 +1562,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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);
|
||||
}
|
||||
@ -1568,7 +1571,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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);
|
||||
}
|
||||
@ -1576,7 +1580,8 @@ public:
|
||||
template <typename OtherValueType, std::ptrdiff_t... OtherDimensions,
|
||||
typename Dummy = std::enable_if_t<std::is_same<
|
||||
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);
|
||||
}
|
||||
@ -1590,8 +1595,8 @@ public:
|
||||
// DimCount and Enabled here are workarounds for a bug in MSVC 2015
|
||||
template <typename SpanType, typename... Dimensions2, size_t DimCount = sizeof...(Dimensions2),
|
||||
bool Enabled = (DimCount > 0), typename = std::enable_if_t<Enabled>>
|
||||
constexpr multi_span<typename SpanType::value_type, Dimensions2::value...> as_span(SpanType s,
|
||||
Dimensions2... dims)
|
||||
constexpr multi_span<typename SpanType::value_type, Dimensions2::value...>
|
||||
as_span(SpanType s, Dimensions2... dims)
|
||||
{
|
||||
static_assert(details::is_multi_span<SpanType>::value,
|
||||
"Variadic as_span() is for reshaping existing spans.");
|
||||
@ -1628,8 +1633,8 @@ multi_span<byte> as_writeable_bytes(multi_span<U, Dimensions...> s) noexcept
|
||||
// on all implementations. It should be considered an experimental extension
|
||||
// to the standard GSL interface.
|
||||
template <typename U, std::ptrdiff_t... Dimensions>
|
||||
constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept
|
||||
-> multi_span<const U, static_cast<std::ptrdiff_t>(
|
||||
constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept -> multi_span<
|
||||
const U, static_cast<std::ptrdiff_t>(
|
||||
multi_span<const byte, Dimensions...>::bounds_type::static_size != dynamic_range
|
||||
? (static_cast<size_t>(
|
||||
multi_span<const byte, Dimensions...>::bounds_type::static_size) /
|
||||
@ -1653,10 +1658,11 @@ constexpr auto as_span(multi_span<const byte, Dimensions...> s) noexcept
|
||||
// on all implementations. It should be considered an experimental extension
|
||||
// to the standard GSL interface.
|
||||
template <typename U, std::ptrdiff_t... Dimensions>
|
||||
constexpr auto as_span(multi_span<byte, Dimensions...> s) noexcept -> multi_span<
|
||||
U, narrow_cast<std::ptrdiff_t>(
|
||||
constexpr auto as_span(multi_span<byte, Dimensions...> s) noexcept
|
||||
-> multi_span<U, narrow_cast<std::ptrdiff_t>(
|
||||
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>(
|
||||
multi_span<byte, Dimensions...>::bounds_type::static_size) /
|
||||
sizeof(U)
|
||||
: dynamic_range)>
|
||||
{
|
||||
@ -1816,8 +1822,8 @@ public:
|
||||
auto d = narrow_cast<size_type>(sizeof(OtherValueType) / sizeof(value_type));
|
||||
|
||||
size_type size = this->bounds().total_size() / d;
|
||||
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())), size,
|
||||
bounds_type{resize_extent(this->bounds().index_bounds(), d),
|
||||
return {const_cast<OtherValueType*>(reinterpret_cast<const OtherValueType*>(this->data())),
|
||||
size, bounds_type{resize_extent(this->bounds().index_bounds(), d),
|
||||
resize_stride(this->bounds().strides(), d)}};
|
||||
}
|
||||
|
||||
@ -2049,7 +2055,7 @@ public:
|
||||
contiguous_span_iterator ret{*this};
|
||||
return ret -= n;
|
||||
}
|
||||
contiguous_span_iterator& operator-=(difference_type n) noexcept { return * this += -n; }
|
||||
contiguous_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
|
||||
difference_type operator-(const contiguous_span_iterator& rhs) const noexcept
|
||||
{
|
||||
Expects(m_validator == rhs.m_validator);
|
||||
@ -2148,16 +2154,13 @@ public:
|
||||
general_span_iterator ret{*this};
|
||||
return ret -= n;
|
||||
}
|
||||
general_span_iterator& operator-=(difference_type n) noexcept { return * this += -n; }
|
||||
general_span_iterator& operator-=(difference_type n) noexcept { return *this += -n; }
|
||||
difference_type operator-(const general_span_iterator& rhs) const noexcept
|
||||
{
|
||||
Expects(m_container == rhs.m_container);
|
||||
return m_itr - rhs.m_itr;
|
||||
}
|
||||
value_type operator[](difference_type n) const noexcept
|
||||
{
|
||||
return (*m_container)[m_itr[n]];
|
||||
}
|
||||
value_type operator[](difference_type n) const noexcept { return (*m_container)[m_itr[n]]; }
|
||||
|
||||
bool operator==(const general_span_iterator& rhs) const noexcept
|
||||
{
|
||||
|
462
include/span.h
462
include/span.h
@ -20,11 +20,11 @@
|
||||
#define GSL_SPAN_H
|
||||
|
||||
#include "gsl_assert.h"
|
||||
#include "gsl_util.h"
|
||||
#include "gsl_byte.h"
|
||||
#include "gsl_util.h"
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@ -39,7 +39,7 @@
|
||||
// blanket turn off warnings from CppCoreCheck for now
|
||||
// so people aren't annoyed by them when running the tool.
|
||||
// more targeted suppressions will be added in a future update to the GSL
|
||||
#pragma warning(disable: 26481 26482 26483 26485 26490 26491 26492 26493 26495)
|
||||
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
|
||||
|
||||
// No MSVC does constexpr fully yet
|
||||
#pragma push_macro("constexpr")
|
||||
@ -82,87 +82,71 @@ namespace gsl
|
||||
template <class ElementType, std::ptrdiff_t Extent = dynamic_extent>
|
||||
class span;
|
||||
|
||||
|
||||
// [views.constants], constants
|
||||
constexpr const std::ptrdiff_t dynamic_extent = -1;
|
||||
|
||||
|
||||
// implementation details
|
||||
namespace details
|
||||
{
|
||||
template <class T>
|
||||
struct is_span_oracle : std::false_type
|
||||
{
|
||||
};
|
||||
template <class T>
|
||||
struct is_span_oracle : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class ElementType, std::ptrdiff_t Extent>
|
||||
struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
|
||||
{
|
||||
};
|
||||
template <class ElementType, std::ptrdiff_t Extent>
|
||||
struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_span : is_span_oracle<std::remove_cv_t<T>>
|
||||
{
|
||||
};
|
||||
template <class T>
|
||||
struct is_span : is_span_oracle<std::remove_cv_t<T>>
|
||||
{
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct is_allowed_pointer_conversion
|
||||
: std::bool_constant<
|
||||
std::is_pointer<From>::value &&
|
||||
std::is_pointer<To>::value &&
|
||||
std::is_convertible<From, To>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
template <class From, class To>
|
||||
struct is_allowed_pointer_conversion
|
||||
: std::bool_constant<std::is_pointer<From>::value && std::is_pointer<To>::value &&
|
||||
std::is_convertible<From, To>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct is_allowed_integral_conversion
|
||||
: std::bool_constant<
|
||||
std::is_integral<From>::value &&
|
||||
std::is_integral<To>::value &&
|
||||
sizeof(From) == sizeof(To) &&
|
||||
alignof(From) == alignof(To) &&
|
||||
std::is_convertible<From, To>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
template <class From, class To>
|
||||
struct is_allowed_integral_conversion
|
||||
: std::bool_constant<std::is_integral<From>::value && std::is_integral<To>::value &&
|
||||
sizeof(From) == sizeof(To) && alignof(From) == alignof(To) &&
|
||||
std::is_convertible<From, To>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <std::ptrdiff_t From, std::ptrdiff_t To>
|
||||
struct is_allowed_extent_conversion
|
||||
: std::bool_constant<
|
||||
From == To ||
|
||||
From == gsl::dynamic_extent ||
|
||||
To == gsl::dynamic_extent
|
||||
>
|
||||
{
|
||||
};
|
||||
template <std::ptrdiff_t From, std::ptrdiff_t To>
|
||||
struct is_allowed_extent_conversion
|
||||
: std::bool_constant<From == To || From == gsl::dynamic_extent || To == gsl::dynamic_extent>
|
||||
{
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct is_allowed_element_type_conversion
|
||||
: std::bool_constant<
|
||||
std::is_same<From, std::remove_cv_t<To>>::value ||
|
||||
template <class From, class To>
|
||||
struct is_allowed_element_type_conversion
|
||||
: std::bool_constant<std::is_same<From, std::remove_cv_t<To>>::value ||
|
||||
is_allowed_pointer_conversion<From, To>::value ||
|
||||
is_allowed_integral_conversion<From, To>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
is_allowed_integral_conversion<From, To>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <class From>
|
||||
struct is_allowed_element_type_conversion<From, byte>
|
||||
template <class From>
|
||||
struct is_allowed_element_type_conversion<From, byte>
|
||||
: std::bool_constant<!std::is_const<From>::value>
|
||||
{
|
||||
};
|
||||
{
|
||||
};
|
||||
|
||||
template <class From>
|
||||
struct is_allowed_element_type_conversion<From, const byte>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
template <class From>
|
||||
struct is_allowed_element_type_conversion<From, const byte> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class Span>
|
||||
class const_span_iterator
|
||||
{
|
||||
public:
|
||||
template <class Span>
|
||||
class const_span_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = typename Span::element_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -174,13 +158,22 @@ public:
|
||||
using reference = const_reference;
|
||||
|
||||
constexpr const_span_iterator() : const_span_iterator(nullptr, 0) {}
|
||||
constexpr const_span_iterator(const Span* span, typename Span::index_type index) : span_(span), index_(index)
|
||||
constexpr const_span_iterator(const Span* span, typename Span::index_type index)
|
||||
: span_(span), index_(index)
|
||||
{
|
||||
Expects(span == nullptr || (index_ >= 0 && index <= span_->length()));
|
||||
}
|
||||
|
||||
constexpr reference operator*() const { Expects(span_); return (*span_)[index_]; }
|
||||
constexpr pointer operator->() const { Expects(span_); return &((*span_)[index_]); }
|
||||
constexpr reference operator*() const
|
||||
{
|
||||
Expects(span_);
|
||||
return (*span_)[index_];
|
||||
}
|
||||
constexpr pointer operator->() const
|
||||
{
|
||||
Expects(span_);
|
||||
return &((*span_)[index_]);
|
||||
}
|
||||
|
||||
constexpr const_span_iterator& operator++() noexcept
|
||||
{
|
||||
@ -240,17 +233,17 @@ public:
|
||||
return index_ - rhs.index_;
|
||||
}
|
||||
|
||||
constexpr reference operator[](difference_type n) const noexcept
|
||||
{
|
||||
return *(*this + n);
|
||||
}
|
||||
constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); }
|
||||
|
||||
constexpr bool operator==(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
return span_ == rhs.span_ && index_ == rhs.index_;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const const_span_iterator& rhs) const noexcept { return !(*this == rhs); }
|
||||
constexpr bool operator!=(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator<(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
@ -258,11 +251,20 @@ public:
|
||||
return index_ < rhs.index_;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const const_span_iterator& rhs) const noexcept { return !(rhs < *this); }
|
||||
constexpr bool operator<=(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(rhs < *this);
|
||||
}
|
||||
|
||||
constexpr bool operator>(const const_span_iterator& rhs) const noexcept { return rhs < *this; }
|
||||
constexpr bool operator>(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
return rhs < *this;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const const_span_iterator& rhs) const noexcept { return !(rhs > *this); }
|
||||
constexpr bool operator>=(const const_span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(rhs > *this);
|
||||
}
|
||||
|
||||
void swap(const_span_iterator& rhs) noexcept
|
||||
{
|
||||
@ -270,18 +272,17 @@ public:
|
||||
std::swap(m_span, rhs.m_span);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const Span* span_;
|
||||
ptrdiff_t index_;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class Span>
|
||||
class span_iterator : public const_span_iterator<Span>
|
||||
{
|
||||
template <class Span>
|
||||
class span_iterator : public const_span_iterator<Span>
|
||||
{
|
||||
using base_type = const_span_iterator<Span>;
|
||||
|
||||
public:
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = typename Span::element_type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -290,80 +291,129 @@ public:
|
||||
using reference = value_type&;
|
||||
|
||||
constexpr span_iterator() : base_type() {}
|
||||
constexpr span_iterator(const Span* span, typename Span::index_type index) : base_type(span, index) {}
|
||||
constexpr span_iterator(const Span* span, typename Span::index_type index)
|
||||
: base_type(span, index)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr reference operator*() const { return const_cast<reference>(base_type::operator*()); }
|
||||
constexpr pointer operator->() const { return const_cast<pointer>(base_type::operator->()); }
|
||||
constexpr reference operator*() const
|
||||
{
|
||||
return const_cast<reference>(base_type::operator*());
|
||||
}
|
||||
constexpr pointer operator->() const
|
||||
{
|
||||
return const_cast<pointer>(base_type::operator->());
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator++() noexcept { base_type::operator++(); return *this; }
|
||||
constexpr span_iterator& operator++() noexcept
|
||||
{
|
||||
base_type::operator++();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator++(int) noexcept { return base_type::operator++(1); }
|
||||
|
||||
constexpr span_iterator& operator--() noexcept { base_type::operator--(); return *this; }
|
||||
constexpr span_iterator& operator--() noexcept
|
||||
{
|
||||
base_type::operator--();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator--(int) noexcept { return base_type::operator--(1); }
|
||||
|
||||
constexpr span_iterator operator+(difference_type n) const noexcept { return base_type::operator+(n); }
|
||||
constexpr span_iterator operator+(difference_type n) const noexcept
|
||||
{
|
||||
return base_type::operator+(n);
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator+=(difference_type n) noexcept { return base_type::operator+=(n); }
|
||||
constexpr span_iterator& operator+=(difference_type n) noexcept
|
||||
{
|
||||
return base_type::operator+=(n);
|
||||
}
|
||||
|
||||
constexpr span_iterator operator-(difference_type n) const noexcept { return base_type::operator-(n); }
|
||||
constexpr span_iterator operator-(difference_type n) const noexcept
|
||||
{
|
||||
return base_type::operator-(n);
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator-=(difference_type n) noexcept { return base_type::operator-=(n); }
|
||||
constexpr span_iterator& operator-=(difference_type n) noexcept
|
||||
{
|
||||
return base_type::operator-=(n);
|
||||
}
|
||||
|
||||
constexpr difference_type operator-(const span_iterator& rhs) const noexcept { return base_type::operator-(rhs); }
|
||||
constexpr difference_type operator-(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return base_type::operator-(rhs);
|
||||
}
|
||||
|
||||
constexpr reference operator[](difference_type n) const noexcept { return *(*this + n); }
|
||||
|
||||
constexpr bool operator==(const span_iterator& rhs) const noexcept { return base_type::operator==(rhs); }
|
||||
constexpr bool operator==(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return base_type::operator==(rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const span_iterator& rhs) const noexcept { return !(*this == rhs); }
|
||||
constexpr bool operator!=(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator<(const span_iterator& rhs) const noexcept { return base_type::operator<(rhs); }
|
||||
constexpr bool operator<(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return base_type::operator<(rhs);
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const span_iterator& rhs) const noexcept { return !(rhs < *this); }
|
||||
constexpr bool operator<=(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(rhs < *this);
|
||||
}
|
||||
|
||||
constexpr bool operator>(const span_iterator& rhs) const noexcept { return rhs < *this; }
|
||||
|
||||
constexpr bool operator>=(const span_iterator& rhs) const noexcept { return !(rhs > *this); }
|
||||
constexpr bool operator>=(const span_iterator& rhs) const noexcept
|
||||
{
|
||||
return !(rhs > *this);
|
||||
}
|
||||
|
||||
void swap(span_iterator& rhs) noexcept { base_type::swap(rhs); }
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Span>
|
||||
constexpr const_span_iterator<Span> operator+(typename const_span_iterator<Span>::difference_type n,
|
||||
template <typename Span>
|
||||
constexpr const_span_iterator<Span>
|
||||
operator+(typename const_span_iterator<Span>::difference_type n,
|
||||
const const_span_iterator<Span>& rhs) noexcept
|
||||
{
|
||||
{
|
||||
return rhs + n;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Span>
|
||||
constexpr const_span_iterator<Span> operator-(typename const_span_iterator<Span>::difference_type n,
|
||||
template <typename Span>
|
||||
constexpr const_span_iterator<Span>
|
||||
operator-(typename const_span_iterator<Span>::difference_type n,
|
||||
const const_span_iterator<Span>& rhs) noexcept
|
||||
{
|
||||
{
|
||||
return rhs - n;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Span>
|
||||
constexpr span_iterator<Span> operator+(typename span_iterator<Span>::difference_type n,
|
||||
template <typename Span>
|
||||
constexpr span_iterator<Span> operator+(typename span_iterator<Span>::difference_type n,
|
||||
const span_iterator<Span>& rhs) noexcept
|
||||
{
|
||||
{
|
||||
return rhs + n;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Span>
|
||||
constexpr span_iterator<Span> operator-(typename span_iterator<Span>::difference_type n,
|
||||
template <typename Span>
|
||||
constexpr span_iterator<Span> operator-(typename span_iterator<Span>::difference_type n,
|
||||
const span_iterator<Span>& rhs) noexcept
|
||||
{
|
||||
{
|
||||
return rhs - n;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
|
||||
// [span], class template span
|
||||
template <class ElementType, std::ptrdiff_t Extent>
|
||||
class span {
|
||||
class span
|
||||
{
|
||||
public:
|
||||
// constants and types
|
||||
using element_type = ElementType;
|
||||
@ -379,78 +429,83 @@ public:
|
||||
constexpr static const index_type extent = Extent;
|
||||
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
constexpr span() noexcept : storage_(nullptr, extent_type<0>())
|
||||
{}
|
||||
constexpr span() noexcept : storage_(nullptr, extent_type<0>()) {}
|
||||
|
||||
constexpr span(nullptr_t) noexcept : span()
|
||||
{}
|
||||
constexpr span(nullptr_t) noexcept : span() {}
|
||||
|
||||
constexpr span(pointer ptr, index_type count) : storage_(ptr, count)
|
||||
{}
|
||||
constexpr span(pointer ptr, index_type count) : storage_(ptr, count) {}
|
||||
|
||||
constexpr span(pointer firstElem, pointer lastElem)
|
||||
: storage_(firstElem, std::distance(firstElem, lastElem))
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
constexpr span(element_type(&arr)[N]) noexcept
|
||||
: storage_(&arr[0], extent_type<N>())
|
||||
{}
|
||||
constexpr span(element_type (&arr)[N]) noexcept : storage_(&arr[0], extent_type<N>())
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
constexpr span(std::array<element_type, N>& arr) noexcept
|
||||
: storage_(&arr[0], extent_type<N>())
|
||||
{}
|
||||
constexpr span(std::array<element_type, N>& arr) noexcept : storage_(&arr[0], extent_type<N>())
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N, class = std::enable_if_t<is_const<element_type>::value>>
|
||||
constexpr span(std::array<std::remove_const_t<element_type>, N>& arr) noexcept
|
||||
: storage_(&arr[0], extent_type<N>())
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
template <size_t N, class = std::enable_if_t<is_const<element_type>::value>>
|
||||
constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
|
||||
: storage_(&arr[0], extent_type<N>())
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
// NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
|
||||
// on Container to be a contiguous sequence container.
|
||||
template <class Container,
|
||||
class = std::enable_if_t<!details::is_span<Container>::value &&
|
||||
std::is_convertible<Container::pointer, pointer>::value &&
|
||||
std::is_convertible<Container::pointer, decltype(std::declval<Container>().data())>::value>
|
||||
>
|
||||
constexpr span(Container& cont) : span(cont.data(), cont.size()) {}
|
||||
|
||||
template <class Container,
|
||||
class = std::enable_if_t<std::is_const<element_type>::value &&
|
||||
class = std::enable_if_t<
|
||||
!details::is_span<Container>::value &&
|
||||
std::is_convertible<Container::pointer, pointer>::value &&
|
||||
std::is_convertible<Container::pointer, decltype(std::declval<Container>().data())>::value>
|
||||
>
|
||||
constexpr span(const Container& cont) : span(cont.data(), cont.size()) {}
|
||||
std::is_convertible<Container::pointer,
|
||||
decltype(std::declval<Container>().data())>::value>>
|
||||
constexpr span(Container& cont) : span(cont.data(), cont.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <class Container,
|
||||
class = std::enable_if_t<
|
||||
std::is_const<element_type>::value && !details::is_span<Container>::value &&
|
||||
std::is_convertible<Container::pointer, pointer>::value &&
|
||||
std::is_convertible<Container::pointer,
|
||||
decltype(std::declval<Container>().data())>::value>>
|
||||
constexpr span(const Container& cont) : span(cont.data(), cont.size())
|
||||
{
|
||||
}
|
||||
|
||||
constexpr span(const span& other) noexcept = default;
|
||||
constexpr span(span&& other) noexcept = default;
|
||||
|
||||
template <class OtherElementType, std::ptrdiff_t OtherExtent,
|
||||
template <
|
||||
class OtherElementType, std::ptrdiff_t OtherExtent,
|
||||
class = std::enable_if_t<
|
||||
details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
|
||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value
|
||||
>
|
||||
>
|
||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
|
||||
constexpr span(const span<OtherElementType, OtherExtent>& other)
|
||||
: storage_(reinterpret_cast<pointer>(other.data()), extent_type<OtherExtent>(other.size()))
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherElementType, std::ptrdiff_t OtherExtent,
|
||||
template <
|
||||
class OtherElementType, std::ptrdiff_t OtherExtent,
|
||||
class = std::enable_if_t<
|
||||
details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
|
||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value
|
||||
>
|
||||
>
|
||||
details::is_allowed_element_type_conversion<OtherElementType, element_type>::value>>
|
||||
constexpr span(span<OtherElementType, OtherExtent>&& other)
|
||||
: storage_(reinterpret_cast<pointer>(other.data()), extent_type<OtherExtent>(other.size()))
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
~span() noexcept = default;
|
||||
constexpr span& operator=(const span& other) noexcept = default;
|
||||
@ -461,14 +516,14 @@ public:
|
||||
constexpr span<element_type, Count> first() const
|
||||
{
|
||||
Expects(Count >= 0 && Count <= size());
|
||||
return { data(), Count };
|
||||
return {data(), Count};
|
||||
}
|
||||
|
||||
template <ptrdiff_t Count>
|
||||
constexpr span<element_type, Count> last() const
|
||||
{
|
||||
Expects(Count >= 0 && Count <= size());
|
||||
return{ data() + (size() - Count), Count };
|
||||
return {data() + (size() - Count), Count};
|
||||
}
|
||||
|
||||
template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
|
||||
@ -476,19 +531,19 @@ public:
|
||||
{
|
||||
Expects((Offset == 0 || Offset > 0 && Offset <= size()) &&
|
||||
(Count == dynamic_extent || Count >= 0 && Offset + Count <= size()));
|
||||
return { data() + Offset, Count == dynamic_extent ? size() - Offset : Count };
|
||||
return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent> first(index_type count) const
|
||||
{
|
||||
Expects(count >= 0 && count <= size());
|
||||
return { data(), count };
|
||||
return {data(), count};
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent> last(index_type count) const
|
||||
{
|
||||
Expects(count >= 0 && count <= size());
|
||||
return { data() + (size() - count), count };
|
||||
return {data() + (size() - count), count};
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent> subspan(index_type offset,
|
||||
@ -496,7 +551,7 @@ public:
|
||||
{
|
||||
Expects((offset == 0 || offset > 0 && offset <= size()) &&
|
||||
(count == dynamic_extent || count >= 0 && offset + count <= size()));
|
||||
return { data() + offset, count == dynamic_extent ? size() - offset : count };
|
||||
return {data() + offset, count == dynamic_extent ? size() - offset : count};
|
||||
}
|
||||
|
||||
// [span.obs], span observers
|
||||
@ -548,8 +603,7 @@ private:
|
||||
Expects(ext.size() == Extent);
|
||||
}
|
||||
|
||||
constexpr extent_type(index_type size)
|
||||
{ Expects(size == Extent); }
|
||||
constexpr extent_type(index_type size) { Expects(size == Extent); }
|
||||
|
||||
constexpr inline index_type size() const noexcept { return Extent; }
|
||||
};
|
||||
@ -560,13 +614,12 @@ private:
|
||||
public:
|
||||
template <index_type Other>
|
||||
explicit constexpr extent_type(extent_type<Other> ext) : size_(ext.size())
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
explicit constexpr extent_type(index_type size) : size_(size)
|
||||
{ Expects(size >= 0); }
|
||||
explicit constexpr extent_type(index_type size) : size_(size) { Expects(size >= 0); }
|
||||
|
||||
constexpr inline index_type size() const noexcept
|
||||
{ return size_; }
|
||||
constexpr inline index_type size() const noexcept { return size_; }
|
||||
|
||||
private:
|
||||
index_type size_;
|
||||
@ -580,12 +633,12 @@ private:
|
||||
{
|
||||
public:
|
||||
template <class OtherExtentType>
|
||||
constexpr storage_type(pointer data, OtherExtentType ext)
|
||||
: ExtentType(ext), data_(data)
|
||||
{ Expects((!data && size() == 0) || (data && size() >= 0)); }
|
||||
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
|
||||
{
|
||||
Expects((!data && size() == 0) || (data && size() >= 0));
|
||||
}
|
||||
|
||||
constexpr inline pointer data() const noexcept
|
||||
{ return data_; }
|
||||
constexpr inline pointer data() const noexcept { return data_; }
|
||||
|
||||
private:
|
||||
pointer data_;
|
||||
@ -594,60 +647,81 @@ private:
|
||||
storage_type<extent_type<Extent>> storage_;
|
||||
};
|
||||
|
||||
|
||||
// [span.comparison], span comparison operators
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator==(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return std::equal(l.begin(), l.end(), r.begin(), r.end()); }
|
||||
{
|
||||
return std::equal(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator!=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return !(l == r); }
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator<(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); }
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator<=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return !(l > r); }
|
||||
{
|
||||
return !(l > r);
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator>(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return r < l; }
|
||||
{
|
||||
return r < l;
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
constexpr bool operator>=(const span<ElementType, Extent>& l, const span<ElementType, Extent>& r)
|
||||
{ return !(l < r); }
|
||||
|
||||
{
|
||||
return !(l < r);
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
// if we only supported compilers with good constexpr support then
|
||||
// this pair of classes could collapse down to a constexpr function
|
||||
|
||||
// we should use a narrow_cast<> to go to size_t, but older compilers may not see it as constexpr
|
||||
// we should use a narrow_cast<> to go to size_t, but older compilers may not see it as
|
||||
// constexpr
|
||||
// and so will fail compilation of the template
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
struct calculate_byte_size :
|
||||
std::integral_constant<std::ptrdiff_t, static_cast<ptrdiff_t>(sizeof(ElementType) * static_cast<size_t>(Extent))>
|
||||
{};
|
||||
struct calculate_byte_size
|
||||
: std::integral_constant<std::ptrdiff_t,
|
||||
static_cast<ptrdiff_t>(sizeof(ElementType) *
|
||||
static_cast<size_t>(Extent))>
|
||||
{
|
||||
};
|
||||
|
||||
template <class ElementType>
|
||||
struct calculate_byte_size<ElementType, dynamic_extent> :
|
||||
std::integral_constant<std::ptrdiff_t, dynamic_extent>
|
||||
{};
|
||||
struct calculate_byte_size<ElementType, dynamic_extent>
|
||||
: std::integral_constant<std::ptrdiff_t, dynamic_extent>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// [span.objectrep], views of object representation
|
||||
template <class ElementType, ptrdiff_t Extent>
|
||||
span<const byte, details::calculate_byte_size<ElementType, Extent>::value> as_bytes(span<ElementType, Extent> s) noexcept
|
||||
{ return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()}; }
|
||||
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
template <class ElementType, ptrdiff_t Extent, class = std::enable_if_t<!std::is_const<ElementType>::value>>
|
||||
span<byte, details::calculate_byte_size<ElementType, Extent>::value> as_writeable_bytes(span<ElementType, Extent> s) noexcept
|
||||
{ return {reinterpret_cast<byte*>(s.data()), s.size_bytes()}; }
|
||||
template <class ElementType, ptrdiff_t Extent,
|
||||
class = std::enable_if_t<!std::is_const<ElementType>::value>>
|
||||
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_writeable_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
|
@ -36,8 +36,7 @@
|
||||
// blanket turn off warnings from CppCoreCheck for now
|
||||
// so people aren't annoyed by them when running the tool.
|
||||
// more targeted suppressions will be added in a future update to the GSL
|
||||
#pragma warning(disable: 26481 26482 26483 26485 26490 26491 26492 26493 26495)
|
||||
|
||||
#pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
|
||||
|
||||
// VS 2013 workarounds
|
||||
#if _MSC_VER <= 1800
|
||||
@ -80,19 +79,19 @@ namespace gsl
|
||||
// (sometimes needlessly) break existing programs when introduced.
|
||||
//
|
||||
|
||||
template<typename CharT, std::ptrdiff_t Extent = dynamic_extent>
|
||||
template <typename CharT, std::ptrdiff_t Extent = dynamic_extent>
|
||||
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>;
|
||||
|
||||
template<std::ptrdiff_t Extent = dynamic_extent>
|
||||
template <std::ptrdiff_t Extent = dynamic_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>;
|
||||
|
||||
template<std::ptrdiff_t Extent = dynamic_extent>
|
||||
template <std::ptrdiff_t Extent = dynamic_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.
|
||||
//
|
||||
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)
|
||||
{
|
||||
auto cur = seq;
|
||||
while ((cur - seq) < max && *cur != Sentinel) ++cur;
|
||||
Ensures(*cur == Sentinel);
|
||||
return{ seq, cur - seq };
|
||||
return {seq, cur - seq};
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ensure_z - creates a span for a czstring or cwzstring.
|
||||
// Will fail fast if a null-terminator cannot be found before
|
||||
// the limit of size_type.
|
||||
//
|
||||
template<typename T>
|
||||
inline span<T, dynamic_extent> ensure_z(T* const & sz, std::ptrdiff_t max = PTRDIFF_MAX)
|
||||
template <typename T>
|
||||
inline span<T, dynamic_extent> ensure_z(T* const& sz, std::ptrdiff_t max = PTRDIFF_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)
|
||||
{
|
||||
auto len = strnlen(sz, narrow_cast<size_t>(max));
|
||||
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)
|
||||
{
|
||||
auto len = strnlen(sz, narrow_cast<size_t>(max));
|
||||
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)
|
||||
{
|
||||
auto len = wcsnlen(sz, narrow_cast<size_t>(max));
|
||||
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)
|
||||
{
|
||||
auto len = wcsnlen(sz, narrow_cast<size_t>(max));
|
||||
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>
|
||||
span<T, dynamic_extent> ensure_z(T(&sz)[N]) { return ensure_z(&sz[0], static_cast<std::ptrdiff_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));
|
||||
}
|
||||
|
||||
template<class Cont>
|
||||
span<typename std::remove_pointer<typename Cont::pointer>::type, dynamic_extent> ensure_z(Cont& cont)
|
||||
template <class 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()));
|
||||
}
|
||||
|
||||
template<typename CharT, std::ptrdiff_t>
|
||||
template <typename CharT, std::ptrdiff_t>
|
||||
class basic_string_span;
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename T>
|
||||
struct is_basic_string_span_oracle : std::false_type
|
||||
{};
|
||||
{
|
||||
};
|
||||
|
||||
template <typename CharT, std::ptrdiff_t Extent>
|
||||
struct is_basic_string_span_oracle<basic_string_span<CharT, Extent>> : std::true_type
|
||||
{};
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_basic_string_span : is_basic_string_span_oracle<std::remove_cv_t<T>>
|
||||
{};
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct length_func
|
||||
{};
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct length_func<char>
|
||||
@ -220,7 +227,6 @@ namespace details
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// string_span and relatives
|
||||
//
|
||||
@ -247,19 +253,17 @@ public:
|
||||
// copy
|
||||
constexpr basic_string_span(const basic_string_span& other) = default;
|
||||
|
||||
// move
|
||||
// move
|
||||
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
|
||||
constexpr basic_string_span(basic_string_span&& other) = default;
|
||||
#else
|
||||
constexpr basic_string_span(basic_string_span&& other)
|
||||
: span_(std::move(other.span_))
|
||||
{}
|
||||
constexpr basic_string_span(basic_string_span&& other) : span_(std::move(other.span_)) {}
|
||||
#endif
|
||||
|
||||
// assign
|
||||
constexpr basic_string_span& operator=(const basic_string_span& other) = default;
|
||||
|
||||
// move assign
|
||||
// move assign
|
||||
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
|
||||
constexpr basic_string_span& operator=(basic_string_span&& other) = default;
|
||||
#else
|
||||
@ -271,211 +275,160 @@ public:
|
||||
#endif
|
||||
|
||||
// from nullptr
|
||||
constexpr basic_string_span(std::nullptr_t ptr) noexcept
|
||||
: span_(ptr)
|
||||
{}
|
||||
constexpr basic_string_span(std::nullptr_t ptr) noexcept : span_(ptr) {}
|
||||
|
||||
// from nullptr and length
|
||||
constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept
|
||||
: span_(ptr, length)
|
||||
{}
|
||||
constexpr basic_string_span(std::nullptr_t ptr, size_type length) noexcept : span_(ptr, length)
|
||||
{
|
||||
}
|
||||
|
||||
// From static arrays - if 0-terminated, remove 0 from the view
|
||||
|
||||
// from static arrays and string literals
|
||||
template<size_t N>
|
||||
constexpr basic_string_span(value_type(&arr)[N]) noexcept
|
||||
: span_(remove_z(arr))
|
||||
{}
|
||||
template <size_t N>
|
||||
constexpr basic_string_span(value_type (&arr)[N]) noexcept : span_(remove_z(arr))
|
||||
{
|
||||
}
|
||||
|
||||
// Those allow 0s within the length, so we do not remove them
|
||||
|
||||
// from raw data and length
|
||||
constexpr basic_string_span(pointer ptr, size_type length) noexcept
|
||||
: span_(ptr, length)
|
||||
{}
|
||||
constexpr basic_string_span(pointer ptr, size_type length) noexcept : span_(ptr, length) {}
|
||||
|
||||
// from string
|
||||
constexpr basic_string_span(std::string& s) noexcept
|
||||
: span_(const_cast<pointer>(s.data()), narrow_cast<std::ptrdiff_t>(s.length()))
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
// from containers. Containers must have .size() and .data() function signatures
|
||||
template <typename Cont,
|
||||
typename = std::enable_if_t<
|
||||
!details::is_basic_string_span<Cont>::value
|
||||
&& !details::is_span<Cont>::value
|
||||
&& std::is_convertible<Cont::pointer, pointer>::value
|
||||
&& std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>
|
||||
>
|
||||
constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size()) {}
|
||||
!details::is_basic_string_span<Cont>::value && !details::is_span<Cont>::value &&
|
||||
std::is_convertible<Cont::pointer, pointer>::value &&
|
||||
std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>>
|
||||
constexpr basic_string_span(Cont& cont) : span_(cont.data(), cont.size())
|
||||
{
|
||||
}
|
||||
|
||||
// disallow creation from temporary containers and strings
|
||||
template <typename Cont,
|
||||
typename = std::enable_if_t<
|
||||
!details::is_basic_string_span<Cont>::value
|
||||
&& !details::is_span<Cont>::value
|
||||
&& std::is_convertible<Cont::pointer, pointer>::value
|
||||
&& std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>
|
||||
>
|
||||
constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size()) {}
|
||||
!details::is_basic_string_span<Cont>::value && !details::is_span<Cont>::value &&
|
||||
std::is_convertible<Cont::pointer, pointer>::value &&
|
||||
std::is_convertible<Cont::pointer, decltype(std::declval<Cont>().data())>::value>>
|
||||
constexpr basic_string_span(const Cont& cont) : span_(cont.data(), cont.size())
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef GSL_MSVC_HAS_SFINAE_SUBSTITUTION_ICE
|
||||
// from span
|
||||
template <typename OtherValueType, std::ptrdiff_t OtherExtent,
|
||||
typename Dummy = std::enable_if_t<
|
||||
std::is_convertible<span<OtherValueType, OtherExtent>, impl_type>::value
|
||||
>
|
||||
>
|
||||
constexpr basic_string_span(span<OtherValueType, OtherExtent> other) noexcept
|
||||
: span_(other)
|
||||
{}
|
||||
std::is_convertible<span<OtherValueType, OtherExtent>, impl_type>::value>>
|
||||
constexpr basic_string_span(span<OtherValueType, OtherExtent> other) noexcept : span_(other)
|
||||
{
|
||||
}
|
||||
#else
|
||||
// from span
|
||||
constexpr basic_string_span(span<value_type, Extent> other) noexcept
|
||||
: span_(other)
|
||||
{}
|
||||
constexpr basic_string_span(span<value_type, Extent> other) noexcept : 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
|
||||
: span_(other)
|
||||
{}
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// from string_span
|
||||
template <typename OtherValueType, std::ptrdiff_t OtherExtent,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value
|
||||
>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
|
||||
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other) noexcept
|
||||
: span_(other.data(), other.length())
|
||||
{}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return length() == 0; }
|
||||
|
||||
// first Count elements
|
||||
template<size_type Count>
|
||||
template <size_type Count>
|
||||
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
|
||||
{
|
||||
return{ span_.first(count) };
|
||||
return {span_.first(count)};
|
||||
}
|
||||
|
||||
// last Count elements
|
||||
template<size_type Count>
|
||||
template <size_type Count>
|
||||
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
|
||||
{
|
||||
return{ span_.last(count) };
|
||||
return {span_.last(count)};
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
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
|
||||
{
|
||||
return span_[idx];
|
||||
}
|
||||
constexpr reference operator[](size_type idx) const noexcept { return span_[idx]; }
|
||||
|
||||
constexpr pointer data() const noexcept
|
||||
{
|
||||
return span_.data();
|
||||
}
|
||||
constexpr pointer data() const noexcept { return span_.data(); }
|
||||
|
||||
// length of the span in elements
|
||||
constexpr size_type length() const noexcept
|
||||
{
|
||||
return span_.size();
|
||||
}
|
||||
constexpr size_type length() const noexcept { return span_.size(); }
|
||||
|
||||
// length of the span in elements
|
||||
constexpr size_type size() const noexcept
|
||||
{
|
||||
return span_.size();
|
||||
}
|
||||
constexpr size_type size() const noexcept { return span_.size(); }
|
||||
|
||||
// length of the span in bytes
|
||||
constexpr size_type size_bytes() const noexcept
|
||||
{
|
||||
return span_.size_bytes();
|
||||
}
|
||||
constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); }
|
||||
|
||||
// length of the span in bytes
|
||||
constexpr size_type length_bytes() const noexcept
|
||||
{
|
||||
return span_.length_bytes();
|
||||
}
|
||||
constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); }
|
||||
|
||||
constexpr iterator begin() const noexcept
|
||||
{
|
||||
return span_.begin();
|
||||
}
|
||||
constexpr iterator begin() const noexcept { return span_.begin(); }
|
||||
|
||||
constexpr iterator end() const noexcept
|
||||
{
|
||||
return span_.end();
|
||||
}
|
||||
constexpr iterator end() const noexcept { return span_.end(); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return span_.cbegin();
|
||||
}
|
||||
constexpr const_iterator cbegin() const noexcept { return span_.cbegin(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return span_.cend();
|
||||
}
|
||||
constexpr const_iterator cend() const noexcept { return span_.cend(); }
|
||||
|
||||
constexpr reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return span_.rbegin();
|
||||
}
|
||||
constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
|
||||
|
||||
constexpr reverse_iterator rend() const noexcept
|
||||
{
|
||||
return span_.rend();
|
||||
}
|
||||
constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return span_.crbegin();
|
||||
}
|
||||
constexpr const_reverse_iterator crbegin() const noexcept { return span_.crbegin(); }
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return span_.crend();
|
||||
}
|
||||
constexpr const_reverse_iterator crend() const noexcept { return span_.crend(); }
|
||||
|
||||
private:
|
||||
|
||||
static impl_type remove_z(pointer const& sz, std::ptrdiff_t max) noexcept
|
||||
{
|
||||
return{ sz, details::length_func<value_type>()(sz, max)};
|
||||
return {sz, details::length_func<value_type>()(sz, max)};
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static impl_type remove_z(value_type(&sz)[N]) noexcept
|
||||
template <size_t N>
|
||||
static impl_type remove_z(value_type (&sz)[N]) noexcept
|
||||
{
|
||||
return remove_z(&sz[0], narrow_cast<std::ptrdiff_t>(N));
|
||||
}
|
||||
@ -483,16 +436,16 @@ private:
|
||||
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>;
|
||||
|
||||
template<std::ptrdiff_t Extent = dynamic_extent>
|
||||
template <std::ptrdiff_t Extent = dynamic_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>;
|
||||
|
||||
template<std::ptrdiff_t Extent = dynamic_extent>
|
||||
template <std::ptrdiff_t Extent = dynamic_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
|
||||
|
||||
template<typename CharT, ptrdiff_t Extent>
|
||||
std::basic_string<typename std::remove_const<CharT>::type> to_string(basic_string_span<CharT, Extent> view)
|
||||
template <typename CharT, ptrdiff_t Extent>
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return{ view.data(), static_cast<size_t>(view.length()) };
|
||||
return {view.data(), static_cast<size_t>(view.length())};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// zero-terminated string span, used to convert
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
@ -548,8 +502,7 @@ public:
|
||||
using impl_type = span<value_type, Extent>;
|
||||
using string_span_type = basic_string_span<value_type, Extent>;
|
||||
|
||||
constexpr basic_zstring_span(impl_type s) noexcept
|
||||
: span_(s)
|
||||
constexpr basic_zstring_span(impl_type s) noexcept : span_(s)
|
||||
{
|
||||
// expects a zero-terminated span
|
||||
Expects(s[s.size() - 1] == '\0');
|
||||
@ -558,19 +511,17 @@ public:
|
||||
// copy
|
||||
constexpr basic_zstring_span(const basic_zstring_span& other) = default;
|
||||
|
||||
// move
|
||||
// move
|
||||
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
|
||||
constexpr basic_zstring_span(basic_zstring_span&& other) = default;
|
||||
#else
|
||||
constexpr basic_zstring_span(basic_zstring_span&& other)
|
||||
: span_(std::move(other.span_))
|
||||
{}
|
||||
constexpr basic_zstring_span(basic_zstring_span&& other) : span_(std::move(other.span_)) {}
|
||||
#endif
|
||||
|
||||
// assign
|
||||
constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;
|
||||
|
||||
// move assign
|
||||
// move assign
|
||||
#ifndef GSL_MSVC_NO_DEFAULT_MOVE_CTOR
|
||||
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
|
||||
#else
|
||||
@ -583,7 +534,10 @@ public:
|
||||
|
||||
constexpr bool empty() const noexcept { return span_.size() == 0; }
|
||||
|
||||
constexpr string_span_type as_string_span() const noexcept { return span_.first(span_.size()-1); }
|
||||
constexpr string_span_type as_string_span() const noexcept
|
||||
{
|
||||
return span_.first(span_.size() - 1);
|
||||
}
|
||||
|
||||
constexpr string_span_type ensure_z() const noexcept { return gsl::ensure_z(span_); }
|
||||
|
||||
@ -609,9 +563,8 @@ using cwzstring_span = basic_zstring_span<const wchar_t, Max>;
|
||||
|
||||
// operator ==
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
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);
|
||||
@ -642,28 +595,28 @@ bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
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);
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
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);
|
||||
@ -673,19 +626,18 @@ bool operator==(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
|
||||
// operator !=
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(one == other);
|
||||
@ -696,27 +648,27 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
|
||||
{
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(one == other);
|
||||
@ -725,20 +677,19 @@ bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
|
||||
// operator<
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
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);
|
||||
@ -750,28 +701,28 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
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);
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
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);
|
||||
@ -781,19 +732,18 @@ bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
|
||||
|
||||
// operator <=
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(other < one);
|
||||
@ -804,27 +754,27 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
|
||||
{
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(other < one);
|
||||
@ -833,19 +783,18 @@ bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
|
||||
// operator>
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return other < one;
|
||||
@ -856,27 +805,27 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
|
||||
{
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return other < one;
|
||||
@ -885,19 +834,18 @@ bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other) noexce
|
||||
|
||||
// operator >=
|
||||
template <typename CharT, std::ptrdiff_t Extent = gsl::dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>
|
||||
>
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
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
|
||||
{
|
||||
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<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value>
|
||||
>
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(one < other);
|
||||
@ -908,27 +856,27 @@ bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexc
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// 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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other) noexcept
|
||||
{
|
||||
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 Dummy = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value
|
||||
&& !gsl::details::is_basic_string_span<T>::value
|
||||
&& std::is_convertible<DataType*, CharT*>::value
|
||||
&& std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>, DataType>::value>
|
||||
>
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other) noexcept
|
||||
{
|
||||
return !(one < other);
|
||||
|
Loading…
Reference in New Issue
Block a user