mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
Refactored to use Expects/Ensures everywhere.
This commit is contained in:
parent
7fc95710b6
commit
d13f6daa75
@ -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
|
||||
#define GSL_GSL_H
|
||||
|
||||
#include "gsl_assert.h" // Ensures/Expects
|
||||
#include "span.h" // span, strided_span...
|
||||
#include "string_span.h" // zstring, string_span, zstring_builder...
|
||||
#include <memory>
|
||||
@ -27,15 +28,13 @@
|
||||
|
||||
// No MSVC does constexpr fully yet
|
||||
#pragma push_macro("constexpr")
|
||||
#define constexpr /* nothing */
|
||||
#define constexpr
|
||||
|
||||
// MSVC 2013 workarounds
|
||||
#if _MSC_VER <= 1800
|
||||
|
||||
// noexcept is not understood
|
||||
#ifndef GSL_THROWS_FOR_TESTING
|
||||
#define noexcept /* nothing */
|
||||
#endif
|
||||
#pragma push_macro("noexcept")
|
||||
#define noexcept
|
||||
|
||||
// turn off some misguided warnings
|
||||
#pragma warning(push)
|
||||
@ -45,11 +44,6 @@
|
||||
|
||||
#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
|
||||
{
|
||||
@ -63,12 +57,6 @@ using std::shared_ptr;
|
||||
template <class 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
|
||||
//
|
||||
@ -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
|
||||
//
|
||||
template <class T, size_t N>
|
||||
T& at(T(&arr)[N], size_t index) { fail_fast_assert(index < N); return arr[index]; }
|
||||
template <class T, size_t N>
|
||||
T& at(T(&arr)[N], size_t index) { Expects(index < N); return arr[index]; }
|
||||
|
||||
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>
|
||||
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
|
||||
// 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!
|
||||
// TODO ensure all arithmetic ops on this type are unavailable
|
||||
@ -216,18 +204,14 @@ namespace std
|
||||
#pragma pop_macro("constexpr")
|
||||
|
||||
#if _MSC_VER <= 1800
|
||||
#pragma warning(pop)
|
||||
|
||||
#ifndef GSL_THROWS_FOR_TESTING
|
||||
#undef noexcept
|
||||
#endif // GSL_THROWS_FOR_TESTING
|
||||
#pragma pop_macro("noexcept")
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // _MSC_VER <= 1800
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(GSL_THROWS_FOR_TESTING)
|
||||
#undef noexcept
|
||||
#endif // GSL_THROWS_FOR_TESTING
|
||||
|
||||
#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
|
141
include/span.h
141
include/span.h
@ -31,19 +31,18 @@
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "fail_fast.h"
|
||||
#include <cassert>
|
||||
#include "gsl_assert.h"
|
||||
|
||||
#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
|
||||
#pragma push_macro("constexpr")
|
||||
#define constexpr /* nothing */
|
||||
|
||||
// MSVC has the potential of bringing in headers where max is a macro
|
||||
#ifdef max
|
||||
#pragma push_macro("max")
|
||||
#undef max
|
||||
#endif
|
||||
#define constexpr
|
||||
|
||||
// VS 2013 workarounds
|
||||
#if _MSC_VER <= 1800
|
||||
@ -52,7 +51,7 @@
|
||||
#define GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
||||
|
||||
// noexcept is not understood
|
||||
#ifndef GSL_THROWS_FOR_TESTING
|
||||
#ifndef GSL_THROWS_ON_CONTRACT_VIOLATION
|
||||
#pragma push_macro("noexcept")
|
||||
#define noexcept /* nothing */
|
||||
#endif
|
||||
@ -66,8 +65,7 @@
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
// In order to test the library, we need it to throw exceptions that we can catch
|
||||
#ifdef GSL_THROWS_FOR_TESTING
|
||||
#ifdef GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma push_macro("noexcept")
|
||||
@ -75,7 +73,7 @@
|
||||
|
||||
#define noexcept /* nothing */
|
||||
|
||||
#endif // GSL_THROWS_FOR_TESTING
|
||||
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
|
||||
|
||||
namespace gsl {
|
||||
@ -143,14 +141,14 @@ public:
|
||||
// Preconditions: component_idx < rank
|
||||
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];
|
||||
}
|
||||
|
||||
// Preconditions: component_idx < rank
|
||||
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];
|
||||
}
|
||||
|
||||
@ -350,7 +348,7 @@ namespace details
|
||||
|
||||
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) {}
|
||||
@ -371,7 +369,7 @@ namespace details
|
||||
size_type linearize(const T& arr) const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -425,8 +423,9 @@ namespace details
|
||||
|
||||
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)
|
||||
{
|
||||
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>
|
||||
@ -439,7 +438,7 @@ namespace details
|
||||
template <typename T, size_t Dim = 0>
|
||||
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);
|
||||
}
|
||||
|
||||
@ -590,8 +589,10 @@ public:
|
||||
|
||||
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");
|
||||
fail_fast_assert(m_ranges.totalSize() <= PTRDIFF_MAX, "Size of the range is larger than the max element of the size type");
|
||||
// Size of the initializer list must match the rank of the array
|
||||
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;
|
||||
@ -748,7 +749,7 @@ public:
|
||||
size_type ret = 0;
|
||||
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];
|
||||
}
|
||||
return ret;
|
||||
@ -874,7 +875,7 @@ public:
|
||||
}
|
||||
// If we're here the preconditions were violated
|
||||
// "pre: there exists s such that r == ++s"
|
||||
fail_fast_assert(false);
|
||||
Expects(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -905,7 +906,8 @@ public:
|
||||
curr[i] = 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;
|
||||
}
|
||||
|
||||
@ -1044,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(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");
|
||||
fail_fast_assert(src.size() == dest.size());
|
||||
Expects(src.size() == dest.size());
|
||||
}
|
||||
|
||||
|
||||
@ -1105,13 +1107,13 @@ namespace details
|
||||
template <typename BoundsType>
|
||||
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::true_type) // dynamic size
|
||||
{
|
||||
fail_fast_assert(totalSize <= PTRDIFF_MAX);
|
||||
Expects(totalSize <= PTRDIFF_MAX);
|
||||
return BoundsType{totalSize};
|
||||
}
|
||||
template <typename BoundsType>
|
||||
BoundsType newBoundsHelperImpl(std::ptrdiff_t totalSize, std::false_type) // static size
|
||||
{
|
||||
fail_fast_assert(BoundsType::static_size == totalSize);
|
||||
Expects(BoundsType::static_size == totalSize);
|
||||
return {};
|
||||
}
|
||||
template <typename BoundsType>
|
||||
@ -1198,7 +1200,7 @@ public:
|
||||
constexpr span(pointer data, bounds_type bounds) noexcept
|
||||
: 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
|
||||
@ -1212,7 +1214,7 @@ public:
|
||||
constexpr span(std::nullptr_t, size_type size) noexcept
|
||||
: span(nullptr, bounds_type{})
|
||||
{
|
||||
fail_fast_assert(size == 0);
|
||||
Expects(size == 0);
|
||||
}
|
||||
|
||||
// default
|
||||
@ -1242,7 +1244,7 @@ public:
|
||||
>
|
||||
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
|
||||
@ -1319,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),
|
||||
"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)) };
|
||||
}
|
||||
|
||||
@ -1328,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),
|
||||
"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)) };
|
||||
}
|
||||
|
||||
@ -1337,13 +1339,13 @@ public:
|
||||
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");
|
||||
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 };
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
@ -1351,13 +1353,13 @@ public:
|
||||
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");
|
||||
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 };
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
@ -1365,13 +1367,13 @@ public:
|
||||
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");
|
||||
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 };
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
@ -1411,10 +1413,11 @@ public:
|
||||
template <bool Enabled = (rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
||||
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();
|
||||
|
||||
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() };
|
||||
}
|
||||
|
||||
@ -1566,7 +1569,7 @@ template <typename Cont>
|
||||
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>>
|
||||
{
|
||||
fail_fast_assert(arr.size() < PTRDIFF_MAX);
|
||||
Expects(arr.size() < PTRDIFF_MAX);
|
||||
return {arr.data(), static_cast<std::ptrdiff_t>(arr.size())};
|
||||
}
|
||||
|
||||
@ -1606,8 +1609,10 @@ public:
|
||||
constexpr strided_span(pointer ptr, size_type size, bounds_type bounds)
|
||||
: m_pdata(ptr), m_bounds(std::move(bounds))
|
||||
{
|
||||
fail_fast_assert((m_bounds.size() > 0 && ptr != nullptr) || m_bounds.size() == 0);
|
||||
fail_fast_assert(this->bounds().total_size() <= size, "Bounds cross data boundaries");
|
||||
Expects((m_bounds.size() > 0 && ptr != nullptr) || m_bounds.size() == 0);
|
||||
// Bounds cross data boundaries
|
||||
Expects(this->bounds().total_size() <= size);
|
||||
(void)size;
|
||||
}
|
||||
|
||||
// from static array of size N
|
||||
@ -1653,10 +1658,11 @@ public:
|
||||
template <bool Enabled = (Rank > 1), typename Ret = std::enable_if_t<Enabled, sliced_type>>
|
||||
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();
|
||||
|
||||
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() };
|
||||
}
|
||||
|
||||
@ -1767,7 +1773,8 @@ public:
|
||||
private:
|
||||
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;
|
||||
ret[Rank - 1] /= d;
|
||||
@ -1778,7 +1785,8 @@ private:
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -1786,12 +1794,16 @@ private:
|
||||
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)
|
||||
{
|
||||
fail_fast_assert(strides[Rank - 1] == 1, "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");
|
||||
// Only strided arrays with regular strides can be resized
|
||||
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)
|
||||
{
|
||||
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;
|
||||
@ -1818,7 +1830,9 @@ private:
|
||||
const Span* m_validator;
|
||||
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) :
|
||||
m_pdata(isbegin ? container->m_pdata : container->m_pdata + container->size()), m_validator(container) {}
|
||||
@ -1876,7 +1890,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
reference operator[](difference_type n) const noexcept
|
||||
@ -1885,7 +1899,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
bool operator!=(const contiguous_span_iterator& rhs) const noexcept
|
||||
@ -1894,7 +1908,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
bool operator<=(const contiguous_span_iterator& rhs) const noexcept
|
||||
@ -1992,7 +2006,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
value_type operator[](difference_type n) const noexcept
|
||||
@ -2001,7 +2015,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
bool operator !=(const general_span_iterator& rhs) const noexcept
|
||||
@ -2010,7 +2024,7 @@ public:
|
||||
}
|
||||
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;
|
||||
}
|
||||
bool operator<=(const general_span_iterator& rhs) const noexcept
|
||||
@ -2046,17 +2060,13 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
|
||||
#undef constexpr
|
||||
#pragma pop_macro("constexpr")
|
||||
|
||||
#ifdef max
|
||||
#pragma pop_macro("max")
|
||||
#endif
|
||||
|
||||
#if _MSC_VER <= 1800
|
||||
#pragma warning(pop)
|
||||
|
||||
#ifndef GSL_THROWS_FOR_TESTING
|
||||
#ifndef GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
#undef noexcept
|
||||
#pragma pop_macro("noexcept")
|
||||
#endif // GSL_THROWS_FOR_TESTING
|
||||
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
|
||||
#undef GSL_MSVC_HAS_VARIADIC_CTOR_BUG
|
||||
|
||||
@ -2064,15 +2074,16 @@ general_span_iterator<Span> operator+(typename general_span_iterator<Span>::diff
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(GSL_THROWS_FOR_TESTING)
|
||||
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
|
||||
|
||||
#undef noexcept
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#pragma pop_macro("noexcept")
|
||||
#endif
|
||||
|
||||
#endif // GSL_THROWS_FOR_TESTING
|
||||
#endif // GSL_THROW_ON_CONTRACT_VIOLATION
|
||||
|
||||
|
||||
#endif // GSL_SPAN_H
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef GSL_STRING_SPAN_H
|
||||
#define GSL_STRING_SPAN_H
|
||||
|
||||
#include "gsl_assert.h"
|
||||
#include "span.h"
|
||||
#include <cstring>
|
||||
|
||||
@ -89,7 +90,7 @@ span<T, dynamic_range> ensure_sentinel(const T* seq, std::ptrdiff_t max = PTRDIF
|
||||
{
|
||||
auto cur = seq;
|
||||
while ((cur - seq) < max && *cur != Sentinel) ++cur;
|
||||
fail_fast_assert(*cur == Sentinel);
|
||||
Ensures(*cur == Sentinel);
|
||||
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)
|
||||
{
|
||||
auto len = strnlen(sz, max);
|
||||
fail_fast_assert(sz[len] == 0);
|
||||
Ensures(sz[len] == 0);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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>
|
||||
|
@ -9,7 +9,7 @@ include_directories(
|
||||
./unittest-cpp
|
||||
)
|
||||
|
||||
add_definitions(-DGSL_THROWS_FOR_TESTING)
|
||||
add_definitions(-DGSL_THROW_ON_CONTRACT_VIOLATION)
|
||||
|
||||
if(MSVC14 OR MSVC12) # has the support we need
|
||||
# remove unnecessary warnings about unchecked iterators
|
||||
|
Loading…
Reference in New Issue
Block a user