mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Merge pull request #206 from neilmacintosh/dev/neilmac/contracts
Rework contract enforcement macros and use everywhere.
This commit is contained in:
commit
3dfda0cfde
@ -1,55 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
|
||||||
//
|
|
||||||
// This code is licensed under the MIT License (MIT).
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef GSL_FAIL_FAST_H
|
|
||||||
#define GSL_FAIL_FAST_H
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#if defined(GSL_THROWS_FOR_TESTING)
|
|
||||||
#include <stdexcept>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace gsl
|
|
||||||
{
|
|
||||||
|
|
||||||
//
|
|
||||||
// Having "fail fast" result in an exception makes unit testing
|
|
||||||
// the GSL classes that rely upon it much simpler.
|
|
||||||
//
|
|
||||||
#if defined(GSL_THROWS_FOR_TESTING)
|
|
||||||
|
|
||||||
struct fail_fast : public std::runtime_error
|
|
||||||
{
|
|
||||||
fail_fast() : std::runtime_error("") {}
|
|
||||||
explicit fail_fast(char const* const message) : std::runtime_error(message) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void fail_fast_assert(bool cond) { if (!cond) throw fail_fast(); }
|
|
||||||
inline void fail_fast_assert(bool cond, const char* const message) { if (!cond) throw fail_fast(message); }
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
inline void fail_fast_assert(bool cond) { if (!cond) std::terminate(); }
|
|
||||||
inline void fail_fast_assert(bool cond, const char* const) { if (!cond) std::terminate(); }
|
|
||||||
|
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GSL_FAIL_FAST_H
|
|
@ -19,6 +19,7 @@
|
|||||||
#ifndef GSL_GSL_H
|
#ifndef GSL_GSL_H
|
||||||
#define GSL_GSL_H
|
#define GSL_GSL_H
|
||||||
|
|
||||||
|
#include "gsl_assert.h" // Ensures/Expects
|
||||||
#include "span.h" // span, strided_span...
|
#include "span.h" // span, strided_span...
|
||||||
#include "string_span.h" // zstring, string_span, zstring_builder...
|
#include "string_span.h" // zstring, string_span, zstring_builder...
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -27,15 +28,13 @@
|
|||||||
|
|
||||||
// No MSVC does constexpr fully yet
|
// No MSVC does constexpr fully yet
|
||||||
#pragma push_macro("constexpr")
|
#pragma push_macro("constexpr")
|
||||||
#define constexpr /* nothing */
|
#define constexpr
|
||||||
|
|
||||||
// MSVC 2013 workarounds
|
// MSVC 2013 workarounds
|
||||||
#if _MSC_VER <= 1800
|
#if _MSC_VER <= 1800
|
||||||
|
|
||||||
// noexcept is not understood
|
// noexcept is not understood
|
||||||
#ifndef GSL_THROWS_FOR_TESTING
|
#pragma push_macro("noexcept")
|
||||||
#define noexcept /* nothing */
|
#define noexcept
|
||||||
#endif
|
|
||||||
|
|
||||||
// turn off some misguided warnings
|
// turn off some misguided warnings
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
@ -45,11 +44,6 @@
|
|||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// In order to test the library, we need it to throw exceptions that we can catch
|
|
||||||
#ifdef GSL_THROWS_FOR_TESTING
|
|
||||||
#define noexcept /* nothing */
|
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
|
||||||
|
|
||||||
|
|
||||||
namespace gsl
|
namespace gsl
|
||||||
{
|
{
|
||||||
@ -63,12 +57,6 @@ using std::shared_ptr;
|
|||||||
template <class T>
|
template <class T>
|
||||||
using owner = T;
|
using owner = T;
|
||||||
|
|
||||||
//
|
|
||||||
// GSL.assert: assertions
|
|
||||||
//
|
|
||||||
#define Expects(x) gsl::fail_fast_assert((x))
|
|
||||||
#define Ensures(x) gsl::fail_fast_assert((x))
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// GSL.util: utilities
|
// GSL.util: utilities
|
||||||
//
|
//
|
||||||
@ -110,14 +98,14 @@ T narrow(U u) { T t = narrow_cast<T>(u); if (static_cast<U>(t) != u) throw narro
|
|||||||
//
|
//
|
||||||
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector
|
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector
|
||||||
//
|
//
|
||||||
template <class T, size_t N>
|
template <class T, size_t N>
|
||||||
T& at(T(&arr)[N], size_t index) { fail_fast_assert(index < N); return arr[index]; }
|
T& at(T(&arr)[N], size_t index) { Expects(index < N); return arr[index]; }
|
||||||
|
|
||||||
template <class T, size_t N>
|
template <class T, size_t N>
|
||||||
T& at(std::array<T, N>& arr, size_t index) { fail_fast_assert(index < N); return arr[index]; }
|
T& at(std::array<T, N>& arr, size_t index) { Expects(index < N); return arr[index]; }
|
||||||
|
|
||||||
template <class Cont>
|
template <class Cont>
|
||||||
typename Cont::value_type& at(Cont& cont, size_t index) { fail_fast_assert(index < cont.size()); return cont[index]; }
|
typename Cont::value_type& at(Cont& cont, size_t index) { Expects(index < cont.size()); return cont[index]; }
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -181,7 +169,7 @@ private:
|
|||||||
|
|
||||||
// we assume that the compiler can hoist/prove away most of the checks inlined from this function
|
// we assume that the compiler can hoist/prove away most of the checks inlined from this function
|
||||||
// if not, we could make them optional via conditional compilation
|
// if not, we could make them optional via conditional compilation
|
||||||
void ensure_invariant() const { fail_fast_assert(ptr_ != nullptr); }
|
void ensure_invariant() const { Expects(ptr_ != nullptr); }
|
||||||
|
|
||||||
// unwanted operators...pointers only point to single objects!
|
// unwanted operators...pointers only point to single objects!
|
||||||
// TODO ensure all arithmetic ops on this type are unavailable
|
// TODO ensure all arithmetic ops on this type are unavailable
|
||||||
@ -216,18 +204,14 @@ namespace std
|
|||||||
#pragma pop_macro("constexpr")
|
#pragma pop_macro("constexpr")
|
||||||
|
|
||||||
#if _MSC_VER <= 1800
|
#if _MSC_VER <= 1800
|
||||||
#pragma warning(pop)
|
|
||||||
|
|
||||||
#ifndef GSL_THROWS_FOR_TESTING
|
|
||||||
#undef noexcept
|
#undef noexcept
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
#pragma pop_macro("noexcept")
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
#endif // _MSC_VER <= 1800
|
#endif // _MSC_VER <= 1800
|
||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#if defined(GSL_THROWS_FOR_TESTING)
|
|
||||||
#undef noexcept
|
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
|
||||||
|
|
||||||
#endif // GSL_GSL_H
|
#endif // GSL_GSL_H
|
||||||
|
78
include/gsl_assert.h
Normal file
78
include/gsl_assert.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// This code is licensed under the MIT License (MIT).
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef GSL_CONTRACTS_H
|
||||||
|
#define GSL_CONTRACTS_H
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
//
|
||||||
|
// There are three configuration options for this GSL implementation's behavior
|
||||||
|
// when pre/post conditions on the GSL types are violated:
|
||||||
|
//
|
||||||
|
// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
|
||||||
|
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
|
||||||
|
// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
|
||||||
|
//
|
||||||
|
#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
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace gsl
|
||||||
|
{
|
||||||
|
struct fail_fast : public std::runtime_error
|
||||||
|
{
|
||||||
|
explicit fail_fast(char const* const message) : std::runtime_error(message) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Expects(cond) if (!(cond)) \
|
||||||
|
throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ GSL_STRINGIFY(__LINE__));
|
||||||
|
#define Ensures(cond) if (!(cond)) \
|
||||||
|
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ GSL_STRINGIFY(__LINE__));
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
|
||||||
|
|
||||||
|
|
||||||
|
#define Expects(cond) if (!(cond)) std::terminate();
|
||||||
|
#define Ensures(cond) if (!(cond)) std::terminate();
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
|
||||||
|
|
||||||
|
#define Expects(cond)
|
||||||
|
#define Ensures(cond)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // GSL_CONTRACTS_H
|
133
include/span.h
133
include/span.h
@ -31,13 +31,18 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "fail_fast.h"
|
#include <cassert>
|
||||||
|
#include "gsl_assert.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
// turn off some warnings that are noisy about our Expects statements
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4127) // conditional expression is constant
|
||||||
|
|
||||||
// No MSVC does constexpr fully yet
|
// No MSVC does constexpr fully yet
|
||||||
#pragma push_macro("constexpr")
|
#pragma push_macro("constexpr")
|
||||||
#define constexpr /* nothing */
|
#define constexpr
|
||||||
|
|
||||||
// VS 2013 workarounds
|
// VS 2013 workarounds
|
||||||
#if _MSC_VER <= 1800
|
#if _MSC_VER <= 1800
|
||||||
@ -46,7 +51,7 @@
|
|||||||
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
||||||
|
|
||||||
// noexcept is not understood
|
// noexcept is not understood
|
||||||
#ifndef GSL_THROWS_FOR_TESTING
|
#ifndef GSL_THROWS_ON_CONTRACT_VIOLATION
|
||||||
#pragma push_macro("noexcept")
|
#pragma push_macro("noexcept")
|
||||||
#define noexcept /* nothing */
|
#define noexcept /* nothing */
|
||||||
#endif
|
#endif
|
||||||
@ -60,8 +65,7 @@
|
|||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// In order to test the library, we need it to throw exceptions that we can catch
|
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
|
||||||
#ifdef GSL_THROWS_FOR_TESTING
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma push_macro("noexcept")
|
#pragma push_macro("noexcept")
|
||||||
@ -69,7 +73,7 @@
|
|||||||
|
|
||||||
#define noexcept /* nothing */
|
#define noexcept /* nothing */
|
||||||
|
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||||
|
|
||||||
|
|
||||||
namespace gsl {
|
namespace gsl {
|
||||||
@ -137,14 +141,14 @@ public:
|
|||||||
// Preconditions: component_idx < rank
|
// Preconditions: component_idx < rank
|
||||||
constexpr reference operator[](size_t component_idx)
|
constexpr reference operator[](size_t component_idx)
|
||||||
{
|
{
|
||||||
fail_fast_assert(component_idx < Rank, "Component index must be less than rank");
|
Expects(component_idx < Rank); // Component index must be less than rank
|
||||||
return elems[component_idx];
|
return elems[component_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preconditions: component_idx < rank
|
// Preconditions: component_idx < rank
|
||||||
constexpr const_reference operator[](size_t component_idx) const noexcept
|
constexpr const_reference operator[](size_t component_idx) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(component_idx < Rank, "Component index must be less than rank");
|
Expects(component_idx < Rank); // Component index must be less than rank
|
||||||
return elems[component_idx];
|
return elems[component_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +348,7 @@ namespace details
|
|||||||
|
|
||||||
BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
|
BoundsRanges(const std::ptrdiff_t* const arr) : Base(arr + 1), m_bound(*arr * this->Base::totalSize())
|
||||||
{
|
{
|
||||||
fail_fast_assert(0 <= *arr);
|
Expects(0 <= *arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundsRanges() : m_bound(0) {}
|
BoundsRanges() : m_bound(0) {}
|
||||||
@ -365,7 +369,7 @@ namespace details
|
|||||||
size_type linearize(const T& arr) const
|
size_type linearize(const T& arr) const
|
||||||
{
|
{
|
||||||
const size_type index = this->Base::totalSize() * arr[Dim];
|
const size_type index = this->Base::totalSize() * arr[Dim];
|
||||||
fail_fast_assert(index < m_bound);
|
Expects(index < m_bound);
|
||||||
return index + this->Base::template linearize<T, Dim + 1>(arr);
|
return index + this->Base::template linearize<T, Dim + 1>(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,8 +423,9 @@ namespace details
|
|||||||
|
|
||||||
template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
|
template <std::ptrdiff_t OtherRange, std::ptrdiff_t... RestOtherRanges>
|
||||||
BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>&other, bool firstLevel = true) : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
|
BoundsRanges(const BoundsRanges<OtherRange, RestOtherRanges...>&other, bool firstLevel = true) : Base(static_cast<const BoundsRanges<RestOtherRanges...>&>(other), false)
|
||||||
{
|
{
|
||||||
fail_fast_assert((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize());
|
Expects((firstLevel && totalSize() <= other.totalSize()) || totalSize() == other.totalSize());
|
||||||
|
(void)firstLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, size_t Dim = 0>
|
template <typename T, size_t Dim = 0>
|
||||||
@ -433,7 +438,7 @@ namespace details
|
|||||||
template <typename T, size_t Dim = 0>
|
template <typename T, size_t Dim = 0>
|
||||||
size_type linearize(const T& arr) const
|
size_type linearize(const T& arr) const
|
||||||
{
|
{
|
||||||
fail_fast_assert(arr[Dim] < CurrentRange, "Index is out of range");
|
Expects(arr[Dim] < CurrentRange); // Index is out of range
|
||||||
return this->Base::totalSize() * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr);
|
return this->Base::totalSize() * arr[Dim] + this->Base::template linearize<T, Dim + 1>(arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,8 +589,10 @@ public:
|
|||||||
|
|
||||||
constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges((const std::ptrdiff_t*)il.begin())
|
constexpr static_bounds(std::initializer_list<size_type> il) : m_ranges((const std::ptrdiff_t*)il.begin())
|
||||||
{
|
{
|
||||||
fail_fast_assert((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) || MyRanges::DynamicNum == il.size(), "Size of the initializer list must match the rank of the array");
|
// Size of the initializer list must match the rank of the array
|
||||||
fail_fast_assert(m_ranges.totalSize() <= PTRDIFF_MAX, "Size of the range is larger than the max element of the size type");
|
Expects((MyRanges::DynamicNum == 0 && il.size() == 1 && *il.begin() == static_size) || MyRanges::DynamicNum == il.size());
|
||||||
|
// Size of the range must be less than the max element of the size type
|
||||||
|
Expects(m_ranges.totalSize() <= PTRDIFF_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static_bounds() = default;
|
constexpr static_bounds() = default;
|
||||||
@ -742,7 +749,7 @@ public:
|
|||||||
size_type ret = 0;
|
size_type ret = 0;
|
||||||
for (size_t i = 0; i < rank; i++)
|
for (size_t i = 0; i < rank; i++)
|
||||||
{
|
{
|
||||||
fail_fast_assert(idx[i] < m_extents[i], "index is out of bounds of the array");
|
Expects(idx[i] < m_extents[i]); // index is out of bounds of the array
|
||||||
ret += idx[i] * m_strides[i];
|
ret += idx[i] * m_strides[i];
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -868,7 +875,7 @@ public:
|
|||||||
}
|
}
|
||||||
// If we're here the preconditions were violated
|
// If we're here the preconditions were violated
|
||||||
// "pre: there exists s such that r == ++s"
|
// "pre: there exists s such that r == ++s"
|
||||||
fail_fast_assert(false);
|
Expects(false);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,7 +906,8 @@ public:
|
|||||||
curr[i] = linear_idx / stride[i];
|
curr[i] = linear_idx / stride[i];
|
||||||
linear_idx = linear_idx % stride[i];
|
linear_idx = linear_idx % stride[i];
|
||||||
}
|
}
|
||||||
fail_fast_assert(!less(curr, index_type{}) && !less(boundary, curr), "index is out of bounds of the array");
|
//index is out of bounds of the array
|
||||||
|
Expects(!less(curr, index_type{}) && !less(boundary, curr));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,7 +1046,7 @@ namespace details
|
|||||||
static_assert(is_bounds<BoundsSrc>::value && is_bounds<BoundsDest>::value, "The src type and dest type must be bounds");
|
static_assert(is_bounds<BoundsSrc>::value && is_bounds<BoundsDest>::value, "The src type and dest type must be bounds");
|
||||||
static_assert(std::is_same<typename BoundsSrc::mapping_type, contiguous_mapping_tag>::value, "The source type must be a contiguous bounds");
|
static_assert(std::is_same<typename BoundsSrc::mapping_type, contiguous_mapping_tag>::value, "The source type must be a contiguous bounds");
|
||||||
static_assert(BoundsDest::static_size == dynamic_range || BoundsSrc::static_size == dynamic_range || BoundsDest::static_size == BoundsSrc::static_size, "The source bounds must have same size as dest bounds");
|
static_assert(BoundsDest::static_size == dynamic_range || BoundsSrc::static_size == dynamic_range || BoundsDest::static_size == BoundsSrc::static_size, "The source bounds must have same size as dest bounds");
|
||||||
fail_fast_assert(src.size() == dest.size());
|
Expects(src.size() == dest.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1099,13 +1107,13 @@ namespace details
|
|||||||
template <typename BoundsType>
|
template <typename BoundsType>
|
||||||
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::true_type) // dynamic size
|
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::true_type) // dynamic size
|
||||||
{
|
{
|
||||||
fail_fast_assert(totalSize <= PTRDIFF_MAX);
|
Expects(totalSize <= PTRDIFF_MAX);
|
||||||
return BoundsType{totalSize};
|
return BoundsType{totalSize};
|
||||||
}
|
}
|
||||||
template <typename BoundsType>
|
template <typename BoundsType>
|
||||||
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size
|
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size
|
||||||
{
|
{
|
||||||
fail_fast_assert(BoundsType::static_size == totalSize);
|
Expects(BoundsType::static_size == totalSize);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
template <typename BoundsType>
|
template <typename BoundsType>
|
||||||
@ -1192,7 +1200,7 @@ public:
|
|||||||
constexpr span(pointer data, bounds_type bounds) noexcept
|
constexpr span(pointer data, bounds_type bounds) noexcept
|
||||||
: m_pdata(data), m_bounds(std::move(bounds))
|
: m_pdata(data), m_bounds(std::move(bounds))
|
||||||
{
|
{
|
||||||
fail_fast_assert((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0);
|
Expects((m_bounds.size() > 0 && data != nullptr) || m_bounds.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span(pointer ptr, size_type size) noexcept
|
constexpr span(pointer ptr, size_type size) noexcept
|
||||||
@ -1206,7 +1214,7 @@ public:
|
|||||||
constexpr span(std::nullptr_t, size_type size) noexcept
|
constexpr span(std::nullptr_t, size_type size) noexcept
|
||||||
: span(nullptr, bounds_type{})
|
: span(nullptr, bounds_type{})
|
||||||
{
|
{
|
||||||
fail_fast_assert(size == 0);
|
Expects(size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default
|
// default
|
||||||
@ -1236,7 +1244,7 @@ public:
|
|||||||
>
|
>
|
||||||
constexpr span(T(&arr)[N], size_type size) : span(arr, typename Helper::bounds_type{size})
|
constexpr span(T(&arr)[N], size_type size) : span(arr, typename Helper::bounds_type{size})
|
||||||
{
|
{
|
||||||
fail_fast_assert(size <= N);
|
Expects(size <= N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// from std array
|
// from std array
|
||||||
@ -1313,7 +1321,7 @@ public:
|
|||||||
{
|
{
|
||||||
static_assert(std::is_standard_layout<U>::value && (bounds_type::static_size == dynamic_range || bounds_type::static_size % static_cast<size_type>(sizeof(U)) == 0),
|
static_assert(std::is_standard_layout<U>::value && (bounds_type::static_size == dynamic_range || bounds_type::static_size % static_cast<size_type>(sizeof(U)) == 0),
|
||||||
"Target type must be standard layout and its size must match the byte array size");
|
"Target type must be standard layout and its size must match the byte array size");
|
||||||
fail_fast_assert((this->bytes() % sizeof(U)) == 0 && (this->bytes() / sizeof(U)) < PTRDIFF_MAX);
|
Expects((this->bytes() % sizeof(U)) == 0 && (this->bytes() / sizeof(U)) < PTRDIFF_MAX);
|
||||||
return { reinterpret_cast<const U*>(this->data()), this->bytes() / static_cast<size_type>(sizeof(U)) };
|
return { reinterpret_cast<const U*>(this->data()), this->bytes() / static_cast<size_type>(sizeof(U)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1322,7 +1330,7 @@ public:
|
|||||||
{
|
{
|
||||||
static_assert(std::is_standard_layout<U>::value && (bounds_type::static_size == dynamic_range || bounds_type::static_size % static_cast<size_t>(sizeof(U)) == 0),
|
static_assert(std::is_standard_layout<U>::value && (bounds_type::static_size == dynamic_range || bounds_type::static_size % static_cast<size_t>(sizeof(U)) == 0),
|
||||||
"Target type must be standard layout and its size must match the byte array size");
|
"Target type must be standard layout and its size must match the byte array size");
|
||||||
fail_fast_assert((this->bytes() % sizeof(U)) == 0);
|
Expects((this->bytes() % sizeof(U)) == 0);
|
||||||
return { reinterpret_cast<U*>(this->data()), this->bytes() / static_cast<size_type>(sizeof(U)) };
|
return { reinterpret_cast<U*>(this->data()), this->bytes() / static_cast<size_type>(sizeof(U)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1331,13 +1339,13 @@ public:
|
|||||||
constexpr span<ValueType, Count> first() const noexcept
|
constexpr span<ValueType, Count> first() const noexcept
|
||||||
{
|
{
|
||||||
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
|
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
|
||||||
fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size()); // ensures we only check condition when needed
|
Expects(bounds_type::static_size != dynamic_range || Count <= this->size());
|
||||||
return { this->data(), Count };
|
return { this->data(), Count };
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span<ValueType, dynamic_range> first(size_type count) const noexcept
|
constexpr span<ValueType, dynamic_range> first(size_type count) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(count <= this->size());
|
Expects(count <= this->size());
|
||||||
return { this->data(), count };
|
return { this->data(), count };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,13 +1353,13 @@ public:
|
|||||||
constexpr span<ValueType, Count> last() const noexcept
|
constexpr span<ValueType, Count> last() const noexcept
|
||||||
{
|
{
|
||||||
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
|
static_assert(bounds_type::static_size == dynamic_range || Count <= bounds_type::static_size, "Index is out of bound");
|
||||||
fail_fast_assert(bounds_type::static_size != dynamic_range || Count <= this->size());
|
Expects(bounds_type::static_size != dynamic_range || Count <= this->size());
|
||||||
return { this->data() + this->size() - Count, Count };
|
return { this->data() + this->size() - Count, Count };
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span<ValueType, dynamic_range> last(size_type count) const noexcept
|
constexpr span<ValueType, dynamic_range> last(size_type count) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(count <= this->size());
|
Expects(count <= this->size());
|
||||||
return { this->data() + this->size() - count, count };
|
return { this->data() + this->size() - count, count };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,13 +1367,13 @@ public:
|
|||||||
constexpr span<ValueType, Count> sub() const noexcept
|
constexpr span<ValueType, Count> sub() const noexcept
|
||||||
{
|
{
|
||||||
static_assert(bounds_type::static_size == dynamic_range || ((Offset == 0 || Offset <= bounds_type::static_size) && Offset + Count <= bounds_type::static_size), "Index is out of bound");
|
static_assert(bounds_type::static_size == dynamic_range || ((Offset == 0 || Offset <= bounds_type::static_size) && Offset + Count <= bounds_type::static_size), "Index is out of bound");
|
||||||
fail_fast_assert(bounds_type::static_size != dynamic_range || ((Offset == 0 || Offset <= this->size()) && Offset + Count <= this->size()));
|
Expects(bounds_type::static_size != dynamic_range || ((Offset == 0 || Offset <= this->size()) && Offset + Count <= this->size()));
|
||||||
return { this->data() + Offset, Count };
|
return { this->data() + Offset, Count };
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr span<ValueType, dynamic_range> sub(size_type offset, size_type count = dynamic_range) const noexcept
|
constexpr span<ValueType, dynamic_range> sub(size_type offset, size_type count = dynamic_range) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert((offset == 0 || offset <= this->size()) && (count == dynamic_range || (offset + count) <= this->size()));
|
Expects((offset == 0 || offset <= this->size()) && (count == dynamic_range || (offset + count) <= this->size()));
|
||||||
return { this->data() + offset, count == dynamic_range ? this->length() - offset : count };
|
return { this->data() + offset, count == dynamic_range ? this->length() - offset : count };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1405,10 +1413,11 @@ public:
|
|||||||
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
||||||
constexpr Ret operator[](size_type idx) const noexcept
|
constexpr Ret operator[](size_type idx) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(idx < m_bounds.size(), "index is out of bounds of the array");
|
Expects(idx < m_bounds.size()); // index is out of bounds of the array
|
||||||
const size_type ridx = idx * m_bounds.stride();
|
const size_type ridx = idx * m_bounds.stride();
|
||||||
|
|
||||||
fail_fast_assert(ridx < m_bounds.total_size(), "index is out of bounds of the underlying data");
|
// index is out of bounds of the underlying data
|
||||||
|
Expects(ridx < m_bounds.total_size());
|
||||||
return Ret{ m_pdata + ridx, m_bounds.slice() };
|
return Ret{ m_pdata + ridx, m_bounds.slice() };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1560,7 +1569,7 @@ template <typename Cont>
|
|||||||
constexpr auto as_span(Cont &arr) -> std::enable_if_t<!details::is_span<std::decay_t<Cont>>::value,
|
constexpr auto as_span(Cont &arr) -> std::enable_if_t<!details::is_span<std::decay_t<Cont>>::value,
|
||||||
span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
|
span<std::remove_reference_t<decltype(arr.size(), *arr.data())>, dynamic_range>>
|
||||||
{
|
{
|
||||||
fail_fast_assert(arr.size() < PTRDIFF_MAX);
|
Expects(arr.size() < PTRDIFF_MAX);
|
||||||
return {arr.data(), static_cast<std::ptrdiff_t>(arr.size())};
|
return {arr.data(), static_cast<std::ptrdiff_t>(arr.size())};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1572,7 +1581,7 @@ constexpr auto as_span(Cont &&arr) -> std::enable_if_t<!details::is_span<std::de
|
|||||||
template <typename CharT, typename Traits, typename Allocator>
|
template <typename CharT, typename Traits, typename Allocator>
|
||||||
constexpr auto as_span(std::basic_string<CharT, Traits, Allocator> &str) -> span<CharT, dynamic_range>
|
constexpr auto as_span(std::basic_string<CharT, Traits, Allocator> &str) -> span<CharT, dynamic_range>
|
||||||
{
|
{
|
||||||
fail_fast_assert(str.size() < PTRDIFF_MAX);
|
Expects(str.size() < PTRDIFF_MAX);
|
||||||
return {&str[0], static_cast<std::ptrdiff_t>(str.size())};
|
return {&str[0], static_cast<std::ptrdiff_t>(str.size())};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1608,8 +1617,10 @@ public:
|
|||||||
constexpr strided_span(pointer ptr, size_type size, bounds_type bounds)
|
constexpr strided_span(pointer ptr, size_type size, bounds_type bounds)
|
||||||
: m_pdata(ptr), m_bounds(std::move(bounds))
|
: m_pdata(ptr), m_bounds(std::move(bounds))
|
||||||
{
|
{
|
||||||
fail_fast_assert((m_bounds.size() > 0 && ptr != nullptr) || m_bounds.size() == 0);
|
Expects((m_bounds.size() > 0 && ptr != nullptr) || m_bounds.size() == 0);
|
||||||
fail_fast_assert(this->bounds().total_size() <= size, "Bounds cross data boundaries");
|
// Bounds cross data boundaries
|
||||||
|
Expects(this->bounds().total_size() <= size);
|
||||||
|
(void)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from static array of size N
|
// from static array of size N
|
||||||
@ -1659,10 +1670,11 @@ public:
|
|||||||
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
||||||
constexpr Ret operator[](size_type idx) const
|
constexpr Ret operator[](size_type idx) const
|
||||||
{
|
{
|
||||||
fail_fast_assert(idx < m_bounds.size(), "index is out of bounds of the array");
|
Expects(idx < m_bounds.size()); // index is out of bounds of the array
|
||||||
const size_type ridx = idx * m_bounds.stride();
|
const size_type ridx = idx * m_bounds.stride();
|
||||||
|
|
||||||
fail_fast_assert(ridx < m_bounds.total_size(), "index is out of bounds of the underlying data");
|
// index is out of bounds of the underlying data
|
||||||
|
Expects(ridx < m_bounds.total_size());
|
||||||
return{ m_pdata + ridx, m_bounds.slice().total_size(), m_bounds.slice() };
|
return{ m_pdata + ridx, m_bounds.slice().total_size(), m_bounds.slice() };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1773,7 +1785,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
|
static index_type resize_extent(const index_type& extent, std::ptrdiff_t d)
|
||||||
{
|
{
|
||||||
fail_fast_assert(extent[Rank - 1] >= d && (extent[Rank-1] % d == 0), "The last dimension of the array needs to contain a multiple of new type elements");
|
// The last dimension of the array needs to contain a multiple of new type elements
|
||||||
|
Expects(extent[Rank - 1] >= d && (extent[Rank - 1] % d == 0));
|
||||||
|
|
||||||
index_type ret = extent;
|
index_type ret = extent;
|
||||||
ret[Rank - 1] /= d;
|
ret[Rank - 1] /= d;
|
||||||
@ -1784,7 +1797,8 @@ private:
|
|||||||
template <bool Enabled = (Rank == 1), typename Dummy = std::enable_if_t<Enabled>>
|
template <bool Enabled = (Rank == 1), typename Dummy = std::enable_if_t<Enabled>>
|
||||||
static index_type resize_stride(const index_type& strides, std::ptrdiff_t , void * = 0)
|
static index_type resize_stride(const index_type& strides, std::ptrdiff_t , void * = 0)
|
||||||
{
|
{
|
||||||
fail_fast_assert(strides[Rank - 1] == 1, "Only strided arrays with regular strides can be resized");
|
// Only strided arrays with regular strides can be resized
|
||||||
|
Expects(strides[Rank - 1] == 1);
|
||||||
|
|
||||||
return strides;
|
return strides;
|
||||||
}
|
}
|
||||||
@ -1792,12 +1806,16 @@ private:
|
|||||||
template <bool Enabled = (Rank > 1), typename Dummy = std::enable_if_t<Enabled>>
|
template <bool Enabled = (Rank > 1), typename Dummy = std::enable_if_t<Enabled>>
|
||||||
static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
|
static index_type resize_stride(const index_type& strides, std::ptrdiff_t d)
|
||||||
{
|
{
|
||||||
fail_fast_assert(strides[Rank - 1] == 1, "Only strided arrays with regular strides can be resized");
|
// Only strided arrays with regular strides can be resized
|
||||||
fail_fast_assert(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0), "The strides must have contiguous chunks of memory that can contain a multiple of new type elements");
|
Expects(strides[Rank - 1] == 1);
|
||||||
|
// The strides must have contiguous chunks of
|
||||||
|
// memory that can contain a multiple of new type elements
|
||||||
|
Expects(strides[Rank - 2] >= d && (strides[Rank - 2] % d == 0));
|
||||||
|
|
||||||
for (size_t i = Rank - 1; i > 0; --i)
|
for (size_t i = Rank - 1; i > 0; --i)
|
||||||
{
|
{
|
||||||
fail_fast_assert((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0), "Only strided arrays with regular strides can be resized");
|
// Only strided arrays with regular strides can be resized
|
||||||
|
Expects((strides[i - 1] >= strides[i]) && (strides[i - 1] % strides[i] == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
index_type ret = strides / d;
|
index_type ret = strides / d;
|
||||||
@ -1824,7 +1842,9 @@ private:
|
|||||||
const Span* m_validator;
|
const Span* m_validator;
|
||||||
void validateThis() const
|
void validateThis() const
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_pdata >= m_validator->m_pdata && m_pdata < m_validator->m_pdata + m_validator->size(), "iterator is out of range of the array");
|
// iterator is out of range of the array
|
||||||
|
Expects(m_pdata >= m_validator->m_pdata &&
|
||||||
|
m_pdata < m_validator->m_pdata + m_validator->size());
|
||||||
}
|
}
|
||||||
contiguous_span_iterator (const Span* container, bool isbegin) :
|
contiguous_span_iterator (const Span* container, bool isbegin) :
|
||||||
m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {}
|
m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {}
|
||||||
@ -1882,7 +1902,7 @@ public:
|
|||||||
}
|
}
|
||||||
difference_type operator-(const contiguous_span_iterator& rhs) const noexcept
|
difference_type operator-(const contiguous_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_validator == rhs.m_validator);
|
Expects(m_validator == rhs.m_validator);
|
||||||
return m_pdata - rhs.m_pdata;
|
return m_pdata - rhs.m_pdata;
|
||||||
}
|
}
|
||||||
reference operator[](difference_type n) const noexcept
|
reference operator[](difference_type n) const noexcept
|
||||||
@ -1891,7 +1911,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool operator==(const contiguous_span_iterator& rhs) const noexcept
|
bool operator==(const contiguous_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_validator == rhs.m_validator);
|
Expects(m_validator == rhs.m_validator);
|
||||||
return m_pdata == rhs.m_pdata;
|
return m_pdata == rhs.m_pdata;
|
||||||
}
|
}
|
||||||
bool operator!=(const contiguous_span_iterator& rhs) const noexcept
|
bool operator!=(const contiguous_span_iterator& rhs) const noexcept
|
||||||
@ -1900,7 +1920,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool operator<(const contiguous_span_iterator& rhs) const noexcept
|
bool operator<(const contiguous_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_validator == rhs.m_validator);
|
Expects(m_validator == rhs.m_validator);
|
||||||
return m_pdata < rhs.m_pdata;
|
return m_pdata < rhs.m_pdata;
|
||||||
}
|
}
|
||||||
bool operator<=(const contiguous_span_iterator& rhs) const noexcept
|
bool operator<=(const contiguous_span_iterator& rhs) const noexcept
|
||||||
@ -1998,7 +2018,7 @@ public:
|
|||||||
}
|
}
|
||||||
difference_type operator-(const general_span_iterator& rhs) const noexcept
|
difference_type operator-(const general_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_container == rhs.m_container);
|
Expects(m_container == rhs.m_container);
|
||||||
return m_itr - rhs.m_itr;
|
return m_itr - rhs.m_itr;
|
||||||
}
|
}
|
||||||
value_type operator[](difference_type n) const noexcept
|
value_type operator[](difference_type n) const noexcept
|
||||||
@ -2007,7 +2027,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool operator==(const general_span_iterator& rhs) const noexcept
|
bool operator==(const general_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_container == rhs.m_container);
|
Expects(m_container == rhs.m_container);
|
||||||
return m_itr == rhs.m_itr;
|
return m_itr == rhs.m_itr;
|
||||||
}
|
}
|
||||||
bool operator !=(const general_span_iterator& rhs) const noexcept
|
bool operator !=(const general_span_iterator& rhs) const noexcept
|
||||||
@ -2016,7 +2036,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool operator<(const general_span_iterator& rhs) const noexcept
|
bool operator<(const general_span_iterator& rhs) const noexcept
|
||||||
{
|
{
|
||||||
fail_fast_assert(m_container == rhs.m_container);
|
Expects(m_container == rhs.m_container);
|
||||||
return m_itr < rhs.m_itr;
|
return m_itr < rhs.m_itr;
|
||||||
}
|
}
|
||||||
bool operator<=(const general_span_iterator& rhs) const noexcept
|
bool operator<=(const general_span_iterator& rhs) const noexcept
|
||||||
@ -2055,10 +2075,10 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
|
|||||||
#if _MSC_VER <= 1800
|
#if _MSC_VER <= 1800
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#ifndef GSL_THROWS_FOR_TESTING
|
#ifndef GSL_THROW_ON_CONTRACT_VIOLATION
|
||||||
#undef noexcept
|
#undef noexcept
|
||||||
#pragma pop_macro("noexcept")
|
#pragma pop_macro("noexcept")
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||||
|
|
||||||
#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
||||||
|
|
||||||
@ -2066,15 +2086,16 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
|
|||||||
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
#if defined(GSL_THROWS_FOR_TESTING)
|
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
|
||||||
|
|
||||||
#undef noexcept
|
#undef noexcept
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
#pragma pop_macro("noexcept")
|
#pragma pop_macro("noexcept")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // GSL_THROWS_FOR_TESTING
|
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||||
|
|
||||||
|
|
||||||
#endif // GSL_SPAN_H
|
#endif // GSL_SPAN_H
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#ifndef GSL_STRING_SPAN_H
|
#ifndef GSL_STRING_SPAN_H
|
||||||
#define GSL_STRING_SPAN_H
|
#define GSL_STRING_SPAN_H
|
||||||
|
|
||||||
|
#include "gsl_assert.h"
|
||||||
#include "span.h"
|
#include "span.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ span<T, dynamic_range> ensure_sentinel(const T* seq, std::ptrdiff_t max = PTRDIF
|
|||||||
{
|
{
|
||||||
auto cur = seq;
|
auto cur = seq;
|
||||||
while ((cur - seq) < max && *cur != Sentinel) ++cur;
|
while ((cur - seq) < max && *cur != Sentinel) ++cur;
|
||||||
fail_fast_assert(*cur == Sentinel);
|
Ensures(*cur == Sentinel);
|
||||||
return{ seq, cur - seq };
|
return{ seq, cur - seq };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,26 +110,26 @@ inline basic_string_span<T, dynamic_range> ensure_z(T* const & sz, std::ptrdiff_
|
|||||||
inline basic_string_span<char, dynamic_range> ensure_z(char* const& sz, std::ptrdiff_t max)
|
inline basic_string_span<char, dynamic_range> ensure_z(char* const& sz, std::ptrdiff_t max)
|
||||||
{
|
{
|
||||||
auto len = strnlen(sz, max);
|
auto len = strnlen(sz, max);
|
||||||
fail_fast_assert(sz[len] == 0);
|
Ensures(sz[len] == 0);
|
||||||
return{ sz, static_cast<std::ptrdiff_t>(len) };
|
return{ sz, static_cast<std::ptrdiff_t>(len) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline basic_string_span<const char, dynamic_range> ensure_z(const char* const& sz, std::ptrdiff_t max)
|
inline basic_string_span<const char, dynamic_range> ensure_z(const char* const& sz, std::ptrdiff_t max)
|
||||||
{
|
{
|
||||||
auto len = strnlen(sz, max);
|
auto len = strnlen(sz, max);
|
||||||
fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
Ensures(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline basic_string_span<wchar_t, dynamic_range> ensure_z(wchar_t* const& sz, std::ptrdiff_t max)
|
inline basic_string_span<wchar_t, dynamic_range> ensure_z(wchar_t* const& sz, std::ptrdiff_t max)
|
||||||
{
|
{
|
||||||
auto len = wcsnlen(sz, max);
|
auto len = wcsnlen(sz, max);
|
||||||
fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
Ensures(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline basic_string_span<const wchar_t, dynamic_range> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max)
|
inline basic_string_span<const wchar_t, dynamic_range> ensure_z(const wchar_t* const& sz, std::ptrdiff_t max)
|
||||||
{
|
{
|
||||||
auto len = wcsnlen(sz, max);
|
auto len = wcsnlen(sz, max);
|
||||||
fail_fast_assert(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
Ensures(sz[len] == 0); return{ sz, static_cast<std::ptrdiff_t>(len) };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T, size_t N>
|
template<class T, size_t N>
|
||||||
|
@ -9,7 +9,7 @@ include_directories(
|
|||||||
./unittest-cpp
|
./unittest-cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-DGSL_THROWS_FOR_TESTING)
|
add_definitions(-DGSL_THROW_ON_CONTRACT_VIOLATION)
|
||||||
|
|
||||||
if(MSVC14 OR MSVC12) # has the support we need
|
if(MSVC14 OR MSVC12) # has the support we need
|
||||||
# remove unnecessary warnings about unchecked iterators
|
# remove unnecessary warnings about unchecked iterators
|
||||||
|
Loading…
Reference in New Issue
Block a user